add -P flag blocking port connections while loading session
[ardour.git] / gtk2_ardour / ardour_ui.cc
index c24d16bcd182da4d24da882c560643b1a0c5d159..0a8209fe22c0da90969df7d7742ce2da209ecf4b 100644 (file)
@@ -49,7 +49,6 @@
 #include "gtkmm2ext/utils.h"
 #include "gtkmm2ext/click_box.h"
 #include "gtkmm2ext/fastmeter.h"
 #include "gtkmm2ext/utils.h"
 #include "gtkmm2ext/click_box.h"
 #include "gtkmm2ext/fastmeter.h"
-#include "gtkmm2ext/stop_signal.h"
 #include "gtkmm2ext/popup.h"
 #include "gtkmm2ext/window_title.h"
 
 #include "gtkmm2ext/popup.h"
 #include "gtkmm2ext/window_title.h"
 
@@ -295,7 +294,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
 
 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
 bool
 
 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
 bool
-ARDOUR_UI::run_startup (bool should_be_new)
+ARDOUR_UI::run_startup (bool should_be_new, string load_template)
 {
        if (_startup == 0) {
                _startup = new ArdourStartup ();
 {
        if (_startup == 0) {
                _startup = new ArdourStartup ();
@@ -308,6 +307,9 @@ ARDOUR_UI::run_startup (bool should_be_new)
        }
 
        _startup->set_new_only (should_be_new);
        }
 
        _startup->set_new_only (should_be_new);
+        if (!load_template.empty()) {
+            _startup->set_load_template( load_template );
+        }
        _startup->present ();
 
        main().run();
        _startup->present ();
 
        main().run();
@@ -343,9 +345,12 @@ ARDOUR_UI::create_engine ()
 
        engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
        engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
 
        engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
        engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
-       engine->Halted.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
        engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
 
        engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
 
+       engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
+
+        ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
+
        post_engine ();
 
        return 0;
        post_engine ();
 
        return 0;
@@ -642,7 +647,7 @@ Please consider the possibilities, and perhaps (re)start JACK."));
 void
 ARDOUR_UI::startup ()
 {
 void
 ARDOUR_UI::startup ()
 {
-       if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
+       if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
                exit (1);
        }
 
                exit (1);
        }
 
@@ -726,10 +731,11 @@ void
 ARDOUR_UI::finish()
 {
        if (_session) {
 ARDOUR_UI::finish()
 {
        if (_session) {
+                int tries = 0;
 
 
-               if (_session->transport_rolling()) {
-                       _session->request_stop ();
-                       usleep (250000);
+               if (_session->transport_rolling() && (++tries < 8)) {
+                       _session->request_stop (false, true);
+                       usleep (10000);
                }
 
                if (_session->dirty()) {
                }
 
                if (_session->dirty()) {
@@ -767,17 +773,18 @@ If you still wish to quit, please use the\n\n\
                _session = 0;
        }
 
                _session = 0;
        }
 
-       ArdourDialog::close_all_dialogs ();
-       engine->stop (true);
         cerr << "Save before quit\n";
        save_ardour_state ();
         cerr << "Save before quit\n";
        save_ardour_state ();
+
+       ArdourDialog::close_all_dialogs ();
+       engine->stop (true);
        quit ();
 }
 
 int
 ARDOUR_UI::ask_about_saving_session (const string & what)
 {
        quit ();
 }
 
 int
 ARDOUR_UI::ask_about_saving_session (const string & what)
 {
-       ArdourDialog window (_("ardour: save session?"));
+       ArdourDialog window (_("Unsaved Session"));
        Gtk::HBox dhbox;  // the hbox for the image and text
        Gtk::Label  prompt_label;
        Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
        Gtk::HBox dhbox;  // the hbox for the image and text
        Gtk::Label  prompt_label;
        Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
@@ -918,8 +925,6 @@ ARDOUR_UI::update_buffer_load ()
                c = _session->capture_load ();
                p = _session->playback_load ();
 
                c = _session->capture_load ();
                p = _session->playback_load ();
 
-               push_buffer_stats (c, p);
-
                snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
                          _session->playback_load(), _session->capture_load());
                buffer_load_label.set_text (buf);
                snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
                          _session->playback_load(), _session->capture_load());
                buffer_load_label.set_text (buf);
@@ -932,7 +937,7 @@ void
 ARDOUR_UI::count_recenabled_streams (Route& route)
 {
        Track* track = dynamic_cast<Track*>(&route);
 ARDOUR_UI::count_recenabled_streams (Route& route)
 {
        Track* track = dynamic_cast<Track*>(&route);
-       if (track && track->diskstream()->record_enabled()) {
+       if (track && track->record_enabled()) {
                rec_enabled_streams += track->n_inputs().n_total();
        }
 }
                rec_enabled_streams += track->n_inputs().n_total();
        }
 }
@@ -1444,14 +1449,14 @@ ARDOUR_UI::transport_stop ()
                return;
        }
 
                return;
        }
 
-       _session->request_stop ();
+       _session->request_stop (false, true);
 }
 
 void
 ARDOUR_UI::transport_stop_and_forget_capture ()
 {
        if (_session) {
 }
 
 void
 ARDOUR_UI::transport_stop_and_forget_capture ()
 {
        if (_session) {
-               _session->request_stop (true);
+               _session->request_stop (true, true);
        }
 }
 
        }
 }
 
@@ -1519,7 +1524,12 @@ ARDOUR_UI::transport_roll ()
        bool rolling = _session->transport_rolling();
 
        if (_session->get_play_loop()) {
        bool rolling = _session->transport_rolling();
 
        if (_session->get_play_loop()) {
-               _session->request_play_loop (false, true);
+               /* XXX it is not possible to just leave seamless loop and keep
+                  playing at present (nov 4th 2009)
+               */
+                if (!Config->get_seamless_loop()) {
+                        _session->request_play_loop (false, true);
+                }
        } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
                /* stop playing a range if we currently are */
                _session->request_play_range (0, true);
        } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
                /* stop playing a range if we currently are */
                _session->request_play_range (0, true);
@@ -1576,7 +1586,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
                        _session->request_play_loop (false, true);
                } else if (_session->get_play_range ()) {
                        affect_transport = false;
                        _session->request_play_loop (false, true);
                } else if (_session->get_play_range ()) {
                        affect_transport = false;
-                       _session->request_play_range (0, true);
+                        _session->request_play_range (0, true);
                } 
        } 
 
                } 
        } 
 
@@ -1694,7 +1704,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream)
                Track* t;
 
                if ((t = dynamic_cast<Track*>(r.get())) != 0) {
                Track* t;
 
                if ((t = dynamic_cast<Track*>(r.get())) != 0) {
-                       t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
+                       t->set_record_enabled (!t->record_enabled());
                }
        }
        if (_session == 0) {
                }
        }
        if (_session == 0) {
@@ -1826,23 +1836,46 @@ ARDOUR_UI::engine_running ()
 }
 
 void
 }
 
 void
-ARDOUR_UI::engine_halted ()
+ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
 {
 {
-       ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
+       if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
+               /* we can't rely on the original string continuing to exist when we are called
+                  again in the GUI thread, so make a copy and note that we need to
+                  free it later.
+               */
+               char *copy = strdup (reason);
+               Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
+               return;
+       }
 
        ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
        ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
 
        update_sample_rate (0);
 
 
        ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
        ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
 
        update_sample_rate (0);
 
-       MessageDialog msg (*editor,
-                          _("\
+        string msgstr;
+
+       /* if the reason is a non-empty string, it means that the backend was shutdown
+          rather than just Ardour.
+       */
+
+       if (strlen (reason)) {
+               msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
+       } else {
+               msgstr = _("\
 JACK has either been shutdown or it\n\
 disconnected Ardour because Ardour\n\
 was not fast enough. Try to restart\n\
 JACK has either been shutdown or it\n\
 disconnected Ardour because Ardour\n\
 was not fast enough. Try to restart\n\
-JACK, reconnect and save the session."));
+JACK, reconnect and save the session.");
+       }
+
+       MessageDialog msg (*editor, msgstr);
        pop_back_splash ();
        msg.run ();
        pop_back_splash ();
        msg.run ();
+
+        if (free_reason) {
+                free ((char*) reason);
+        }
 }
 
 int32_t
 }
 
 int32_t
@@ -1940,24 +1973,29 @@ ARDOUR_UI::stop_blinking ()
 
 /** Ask the user for the name of a new shapshot and then take it.
  */
 
 /** Ask the user for the name of a new shapshot and then take it.
  */
+
 void
 void
-ARDOUR_UI::snapshot_session ()
+ARDOUR_UI::snapshot_session (bool switch_to_it)
 {
        ArdourPrompter prompter (true);
        string snapname;
 {
        ArdourPrompter prompter (true);
        string snapname;
-       char timebuf[128];
-       time_t n;
-       struct tm local_time;
-
-       time (&n);
-       localtime_r (&n, &local_time);
-       strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
 
        prompter.set_name ("Prompter");
        prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
        prompter.set_title (_("Take Snapshot"));
 
        prompter.set_name ("Prompter");
        prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
        prompter.set_title (_("Take Snapshot"));
-       prompter.set_prompt (_("Name of New Snapshot"));
-       prompter.set_initial_text (timebuf);
+       prompter.set_title (_("Take Snapshot"));
+       prompter.set_prompt (_("Name of new snapshot"));
+
+        if (!switch_to_it) {
+                char timebuf[128];
+                time_t n;
+                struct tm local_time;
+                
+                time (&n);
+                localtime_r (&n, &local_time);
+                strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
+                prompter.set_initial_text (timebuf);
+        }
 
   again:
        switch (prompter.run()) {
 
   again:
        switch (prompter.run()) {
@@ -1987,7 +2025,7 @@ ARDOUR_UI::snapshot_session ()
                vector<string> n = get_file_names_no_extension (p);
                if (find (n.begin(), n.end(), snapname) != n.end()) {
 
                vector<string> n = get_file_names_no_extension (p);
                if (find (n.begin(), n.end(), snapname) != n.end()) {
 
-                       ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
+                       ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
                        Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
                        confirm.get_vbox()->pack_start (m, true, true);
                        confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
                        Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
                        confirm.get_vbox()->pack_start (m, true, true);
                        confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
@@ -2000,7 +2038,7 @@ ARDOUR_UI::snapshot_session ()
                }
 
                if (do_save) {
                }
 
                if (do_save) {
-                       save_state (snapname);
+                       save_state (snapname, switch_to_it);
                }
                break;
        }
                }
                break;
        }
@@ -2011,13 +2049,13 @@ ARDOUR_UI::snapshot_session ()
 }
 
 void
 }
 
 void
-ARDOUR_UI::save_state (const string & name)
+ARDOUR_UI::save_state (const string & name, bool switch_to_it)
 {
 {
-       save_state_canfail (name);
+       save_state_canfail (name, switch_to_it);
 }
 
 int
 }
 
 int
-ARDOUR_UI::save_state_canfail (string name)
+ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
 {
        if (_session) {
                int ret;
 {
        if (_session) {
                int ret;
@@ -2026,7 +2064,7 @@ ARDOUR_UI::save_state_canfail (string name)
                        name = _session->snap_name();
                }
 
                        name = _session->snap_name();
                }
 
-               if ((ret = _session->save_state (name)) != 0) {
+               if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
                        return ret;
                }
        }
                        return ret;
                }
        }
@@ -2067,7 +2105,7 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff)
        }
 
        Session::RecordState const r = _session->record_status ();
        }
 
        Session::RecordState const r = _session->record_status ();
-       bool const h = _session->have_rec_enabled_diskstream ();
+       bool const h = _session->have_rec_enabled_track ();
 
        if (r == Session::Enabled || (r == Session::Recording && !h)) {
                if (onoff) {
 
        if (r == Session::Enabled || (r == Session::Recording && !h)) {
                if (onoff) {
@@ -2355,7 +2393,7 @@ ARDOUR_UI::loading_message (const std::string& /*msg*/)
 
 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
 int
 
 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
 int
-ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
+ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
 {
        Glib::ustring session_name;
        Glib::ustring session_path;
 {
        Glib::ustring session_name;
        Glib::ustring session_path;
@@ -2363,6 +2401,11 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
        int ret = -1;
        bool likely_new = false;
 
        int ret = -1;
        bool likely_new = false;
 
+        if (! load_template.empty()) {
+            should_be_new = true;
+            template_name = load_template;
+        }
+
        while (ret != 0) {
 
                if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
        while (ret != 0) {
 
                if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
@@ -2382,7 +2425,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
 
                } else {
 
 
                } else {
 
-                       bool const apply = run_startup (should_be_new);
+                       bool const apply = run_startup (should_be_new, load_template);
                        if (!apply) {
                                if (quit_on_cancel) {
                                        exit (1);
                        if (!apply) {
                                if (quit_on_cancel) {
                                        exit (1);
@@ -2744,7 +2787,7 @@ require some unused files to continue to exist."));
                return;
        }
 
                return;
        }
 
-       ArdourDialog results (_("ardour: cleanup"), true, false);
+       ArdourDialog results (_("Clean-up"), true, false);
 
        struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
            CleanupResultsModelColumns() {
 
        struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
            CleanupResultsModelColumns() {
@@ -3106,62 +3149,11 @@ ARDOUR_UI::xrun_handler(nframes_t where)
        }
 }
 
        }
 }
 
-void
-ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
-{
-       time_t now;
-       time (&now);
-
-       while (disk_buffer_stats.size() > 60) {
-               disk_buffer_stats.pop_front ();
-       }
-
-       disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
-}
-
-void
-ARDOUR_UI::write_buffer_stats ()
-{
-       std::ofstream fout;
-       struct tm tm;
-       char buf[64];
-       char path[PATH_MAX+1];  int fd;
-
-       strcpy (path, "ardourBufferingXXXXXX");
-
-       if ((fd = mkstemp (path )) < 0) {
-               cerr << X_("cannot find temporary name for buffer stats") << endl;
-               return;
-       }
-       
-       fout.open (path);
-       close (fd);
-
-       if (!fout) {
-               cerr << string_compose (X_("cannot open file %1 for buffer stats"), path) << endl;
-               return;
-       }
-
-       for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
-               localtime_r (&(*i).when, &tm);
-               strftime (buf, sizeof (buf), "%T", &tm);
-               fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
-       }
-       
-       disk_buffer_stats.clear ();
-
-       fout.close ();
-
-       cerr << "buffering statistics can be found in: " << path << endl;
-}
-
 void
 ARDOUR_UI::disk_overrun_handler ()
 {
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
 
 void
 ARDOUR_UI::disk_overrun_handler ()
 {
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
 
-       write_buffer_stats ();
-
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
                MessageDialog* msg = new MessageDialog (*editor, _("\
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
                MessageDialog* msg = new MessageDialog (*editor, _("\
@@ -3180,8 +3172,6 @@ ARDOUR_UI::disk_underrun_handler ()
 {
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
 
 {
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
 
-       write_buffer_stats ();
-
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
                MessageDialog* msg = new MessageDialog (*editor,
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
                MessageDialog* msg = new MessageDialog (*editor,
@@ -3364,7 +3354,7 @@ ARDOUR_UI::record_state_changed ()
        }
 
        Session::RecordState const r = _session->record_status ();
        }
 
        Session::RecordState const r = _session->record_status ();
-       bool const h = _session->have_rec_enabled_diskstream ();
+       bool const h = _session->have_rec_enabled_track ();
 
        if (r == Session::Recording && h)  {
                big_clock.set_widget_name ("BigClockRecording");
 
        if (r == Session::Recording && h)  {
                big_clock.set_widget_name ("BigClockRecording");