make "New Session" open NSD on the right page
[ardour.git] / gtk2_ardour / ardour_ui.cc
index febdbab088f28809beb076662c2e7160800c7b45..74234bb12aef06cb554e70826d65e829ffc7a1d3 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <algorithm>
 #include <gtkmm2ext/fastmeter.h>
 #include <gtkmm2ext/stop_signal.h>
 #include <gtkmm2ext/popup.h>
+#include <gtkmm2ext/window_title.h>
 
 #include <midi++/port.h>
 #include <midi++/mmc.h>
 
 #include <ardour/ardour.h>
+#include <ardour/profile.h>
 #include <ardour/session_route.h>
 #include <ardour/port.h>
 #include <ardour/audioengine.h>
@@ -88,13 +89,12 @@ ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
 
 sigc::signal<void,bool> ARDOUR_UI::Blink;
 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
-sigc::signal<void>      ARDOUR_UI::MidRapidScreenUpdate;
 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
 
 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
 
-       : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
+       : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
          
          primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
          secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
@@ -180,15 +180,13 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
        location_ui = 0;
        open_session_selector = 0;
        have_configure_timeout = false;
-       have_disk_overrun_displayed = false;
-       have_disk_underrun_displayed = false;
+       have_disk_speed_dialog_displayed = false;
        _will_create_new_session_automatically = false;
        session_loaded = false;
        last_speed_displayed = -1.0f;
        keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
 
        can_save_keybindings = false;
-       Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
 
        last_configure_time.tv_sec = 0;
        last_configure_time.tv_usec = 0;
@@ -265,10 +263,6 @@ ARDOUR_UI::set_engine (AudioEngine& e)
        AudioFileSource::set_build_peakfiles (true);
        AudioFileSource::set_build_missing_peakfiles (true);
 
-       if (AudioSource::start_peak_thread ()) {
-               throw failed_constructor();
-       }
-
        /* set default clock modes */
 
        primary_clock.set_mode (AudioClock::SMPTE);
@@ -306,8 +300,6 @@ ARDOUR_UI::~ARDOUR_UI ()
        if (add_route_dialog) {
                delete add_route_dialog;
        }
-
-       AudioSource::stop_peak_thread ();
 }
 
 gint
@@ -436,30 +428,108 @@ ARDOUR_UI::save_ardour_state ()
        save_keybindings ();
 }
 
+gint
+ARDOUR_UI::autosave_session ()
+{
+        if (!Config->get_periodic_safety_backups())
+                return 1;
+        
+        if (session) {
+                session->maybe_write_autosave();
+        }
+
+        return 1;
+}
+
+void
+ARDOUR_UI::update_autosave ()
+{
+        ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
+        
+        if (session->dirty()) {
+                if (_autosave_connection.connected()) {
+                        _autosave_connection.disconnect();
+                }
+
+                _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
+                                                                   Config->get_periodic_safety_backup_interval() * 1000);
+
+        } else {
+                if (_autosave_connection.connected()) {
+                        _autosave_connection.disconnect();
+                }               
+        }
+}
+
 void
 ARDOUR_UI::startup ()
 {
-       if (engine->is_realtime()) {
+       check_memory_locking();
+}
+
+void
+ARDOUR_UI::no_memory_warning ()
+{
+       XMLNode node (X_("no-memory-warning"));
+       Config->add_instant_xml (node, get_user_ardour_path());
+}
+
+void
+ARDOUR_UI::check_memory_locking ()
+{
+#ifdef __APPLE__
+       /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
+       return;
+#else // !__APPLE__
+
+       XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
+
+       if (engine->is_realtime() && memory_warning_node == 0) {
 
                struct rlimit limits;
-               
+               int64_t ram;
+               long pages, page_size;
+
+               if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
+                       ram = 0;
+               } else {
+                       ram = (int64_t) pages * (int64_t) page_size;
+               }
+
                if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
                        return;
                }
                
                if (limits.rlim_cur != RLIM_INFINITY) {
-                       MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
-                                            "This might cause Ardour to run out of memory before your system "
-                                            "runs out of memory. \n\n"
-                                            "You can view the memory limit with 'ulimit -l', "
-                                            "and it is normally controlled by /etc/security/limits.conf"));
+
+                       if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
                        
-                       editor->ensure_float (msg);
-                       msg.run ();
+
+                               MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
+                                                    "This might cause Ardour to run out of memory before your system "
+                                                    "runs out of memory. \n\n"
+                                                    "You can view the memory limit with 'ulimit -l', "
+                                                    "and it is normally controlled by /etc/security/limits.conf"));
+                               
+                               VBox* vbox = msg.get_vbox();
+                               HBox hbox;
+                               CheckButton cb (_("Do not show this window again"));
+                               
+                               cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
+                               
+                               hbox.pack_start (cb, true, false);
+                               vbox->pack_start (hbox);
+                               hbox.show_all ();
+                               
+                               editor->ensure_float (msg);
+                               msg.run ();
+                       }
                }
        }
+#endif // !__APPLE__
 }
 
+
 void
 ARDOUR_UI::finish()
 {
@@ -582,13 +652,6 @@ ARDOUR_UI::every_point_one_seconds ()
        return TRUE;
 }
 
-gint
-ARDOUR_UI::every_point_oh_five_seconds ()
-{
-       MidRapidScreenUpdate(); /* EMIT_SIGNAL */
-       return true;
-}
-
 gint
 ARDOUR_UI::every_point_zero_one_seconds ()
 {
@@ -612,11 +675,11 @@ ARDOUR_UI::update_sample_rate (nframes_t ignored)
                nframes_t rate = engine->frame_rate();
                
                if (fmod (rate, 1000.0) != 0.0) {
-                       snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"), 
+                       snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"), 
                                  (float) rate/1000.0f,
                                  (engine->frames_per_cycle() / (float) rate) * 1000.0f);
                } else {
-                       snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"), 
+                       snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"), 
                                  rate/1000,
                                  (engine->frames_per_cycle() / (float) rate) * 1000.0f);
                }
@@ -629,7 +692,7 @@ void
 ARDOUR_UI::update_cpu_load ()
 {
        char buf[32];
-       snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
+       snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
        cpu_load_label.set_text (buf);
 }
 
@@ -708,40 +771,6 @@ ARDOUR_UI::update_wall_clock ()
 
        return TRUE;
 }
-void
-ARDOUR_UI::control_methods_adjusted ()
-
-{
-       int which_method;
-
-       which_method = (int) online_control_button->adjustment.get_value();
-       switch (which_method) {
-       case 0:
-               allow_mmc_and_local ();
-               break;
-       case 1:
-               allow_mmc_only ();
-               break;
-       case 2:
-               allow_local_only ();
-               break;
-       default:
-               fatal << _("programming error: impossible control method") << endmsg;
-       }
-}
-       
-
-void
-ARDOUR_UI::mmc_device_id_adjusted ()
-
-{
-#if 0
-       if (mmc) {
-               int dev_id = (int) mmc_id_button->adjustment.get_value();
-               mmc->set_device_id (dev_id);
-       }
-#endif
-}
 
 gint
 ARDOUR_UI::session_menu (GdkEventButton *ev)
@@ -988,7 +1017,8 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
                                if (how_many == 1) {
                                        error << _("could not create a new audio track") << endmsg;
                                } else {
-                                       error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
+                                       error << string_compose (_("could only create %1 of %2 new audio %3"), 
+                                                                tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
                                }
                        }
 
@@ -1019,6 +1049,7 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
        }
 
        catch (...) {
+               cerr << "About to complain about JACK\n";
                MessageDialog msg (*editor, 
                                   _("There are insufficient JACK ports available\n\
 to create a new track or bus.\n\
@@ -1136,8 +1167,6 @@ ARDOUR_UI::remove_last_capture()
 void
 ARDOUR_UI::transport_record ()
 {
-       cerr << "transport record\n";
-
        if (session) {
                switch (session->record_status()) {
                case Session::Disabled:
@@ -1310,24 +1339,6 @@ ARDOUR_UI::map_transport_state ()
        }
 }
 
-void
-ARDOUR_UI::allow_local_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_and_local ()
-{
-
-}
-
 void
 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
 {
@@ -1559,6 +1570,8 @@ ARDOUR_UI::name_io_setup (AudioEngine& engine,
        }
 }
 
+/** Ask the user for the name of a new shapshot and then take it.
+ */
 void
 ARDOUR_UI::snapshot_session ()
 {
@@ -1732,21 +1745,35 @@ ARDOUR_UI::save_template ()
        }
 }
 
-void
+bool
 ARDOUR_UI::new_session (std::string predetermined_path)
 {
        string session_name;
        string session_path;
 
+       if (!engine->connected()) {
+               MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
+               msg.run ();
+               return false;
+       }
+
        int response = Gtk::RESPONSE_NONE;
 
        new_session_dialog->set_modal(true);
        new_session_dialog->set_name (predetermined_path);
        new_session_dialog->reset_recent();
        new_session_dialog->show();
+       new_session_dialog->set_current_page (0);
 
        do {
                response = new_session_dialog->run ();
+
+               if (!engine->connected()) {
+                       new_session_dialog->hide ();
+                       MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
+                       msg.run ();
+                       return false;
+               }
                
                _session_is_new = false;
 
@@ -1756,7 +1783,7 @@ ARDOUR_UI::new_session (std::string predetermined_path)
                                quit();
                        }
                        new_session_dialog->hide ();
-                       return;
+                       return false;
 
                } else if (response == Gtk::RESPONSE_NONE) {
 
@@ -1907,15 +1934,20 @@ ARDOUR_UI::new_session (std::string predetermined_path)
                                        uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
                                        uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
                                                        
-                                       build_session (session_path,
-                                                      session_name,
-                                                      cchns,
-                                                      mchns,
-                                                      iconnect,
-                                                      oconnect,
-                                                      nphysin,
-                                                      nphysout, 
-                                                      engine->frame_rate() * 60 * 5);
+                                       if (build_session (session_path,
+                                                          session_name,
+                                                          cchns,
+                                                          mchns,
+                                                          iconnect,
+                                                          oconnect,
+                                                          nphysin,
+                                                          nphysout, 
+                                                          engine->frame_rate() * 60 * 5)) {
+
+                                               response = Gtk::RESPONSE_NONE;
+                                               new_session_dialog->reset ();
+                                               continue;
+                                       }
                                }
                        }
                }
@@ -1926,6 +1958,7 @@ ARDOUR_UI::new_session (std::string predetermined_path)
        show();
        new_session_dialog->get_window()->set_cursor();
        new_session_dialog->hide();
+       return true;
 }
 
 void
@@ -1981,6 +2014,7 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
                session->set_clean ();
        }
 
+       editor->edit_cursor_position (true);
        return 0;
 }
 
@@ -2014,7 +2048,8 @@ ARDOUR_UI::build_session (const string & path, const string & snap_name,
 
        catch (...) {
 
-               error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
+               MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
+               msg.run ();
                return -1;
        }
 
@@ -2249,7 +2284,7 @@ releasing %4 %5bytes of disk space"));
 }
 
 void
-ARDOUR_UI::add_route ()
+ARDOUR_UI::add_route (Gtk::Window* float_window)
 {
        int count;
 
@@ -2259,7 +2294,9 @@ ARDOUR_UI::add_route ()
 
        if (add_route_dialog == 0) {
                add_route_dialog = new AddRouteDialog;
-               editor->ensure_float (*add_route_dialog);
+               if (float_window) {
+                       add_route_dialog->set_transient_for (*float_window);
+               }
        }
 
        if (add_route_dialog->is_visible()) {
@@ -2366,18 +2403,18 @@ ARDOUR_UI::halt_on_xrun_message ()
 void
 ARDOUR_UI::disk_overrun_handler ()
 {
-       ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
+       ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
 
-       if (!have_disk_overrun_displayed) {
-               have_disk_overrun_displayed = true;
-               MessageDialog msg (*editor, X_("diskrate dialog"), _("\
+       if (!have_disk_speed_dialog_displayed) {
+               have_disk_speed_dialog_displayed = true;
+               MessageDialog* msg = new MessageDialog (*editor, _("\
 The disk system on your computer\n\
 was not able to keep up with Ardour.\n\
 \n\
 Specifically, it failed to write data to disk\n\
 quickly enough to keep up with recording.\n"));
-               msg.run ();
-               have_disk_overrun_displayed = false;
+               msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
+               msg->show_all ();
        }
 }
 
@@ -2386,29 +2423,24 @@ ARDOUR_UI::disk_underrun_handler ()
 {
        ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
 
-       if (!have_disk_underrun_displayed) {
-               have_disk_underrun_displayed = true;
-               MessageDialog msg (*editor,
-                       (_("The disk system on your computer\n\
+       if (!have_disk_speed_dialog_displayed) {
+               have_disk_speed_dialog_displayed = true;
+               MessageDialog* msg = new MessageDialog (*editor,
+                                  _("The disk system on your computer\n\
 was not able to keep up with Ardour.\n\
 \n\
 Specifically, it failed to read data from disk\n\
-quickly enough to keep up with playback.\n")));
-               msg.run ();
-               have_disk_underrun_displayed = false;
+quickly enough to keep up with playback.\n"));
+               msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
+               msg->show_all ();
        } 
 }
 
 void
-ARDOUR_UI::disk_underrun_message_gone ()
+ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
 {
-       have_disk_underrun_displayed = false;
-}
-
-void
-ARDOUR_UI::disk_overrun_message_gone ()
-{
-       have_disk_underrun_displayed = false;
+       have_disk_speed_dialog_displayed = false;
+       delete msg;
 }
 
 int
@@ -2587,6 +2619,9 @@ ARDOUR_UI::save_keybindings ()
 bool
 ARDOUR_UI::first_idle ()
 {
+       if (session) {
+               session->allow_auto_play (true);
+       }
        can_save_keybindings = true;
        return false;
 }
@@ -2616,23 +2651,22 @@ void
 ARDOUR_UI::TransportControllable::set_value (float val)
 {
        if (type == ShuttleControl) {
-
                double fract;
 
-               if (val == 63.0f) {
+               if (val == 0.5f) {
                        fract = 0.0;
                } else {
-                       if (val < 63.0f) {
-                               fract = -((63.0f - val)/63.0f);
+                       if (val < 0.5f) {
+                               fract = -((0.5f - val)/0.5f);
                        } else {
-                               fract = ((val - 63.0f)/63.0f);
+                               fract = ((val - 0.5f)/0.5f);
                        }
                }
                
                ui.set_shuttle_fract (fract);
                return;
        }
-               
+
        if (val < 0.5f) {
                /* do nothing: these are radio-style actions */
                return;
@@ -2670,7 +2704,7 @@ ARDOUR_UI::TransportControllable::set_value (float val)
                return;
        }
 
-       Glib::RefPtr<Action> act = ActionManager::get_action ("transport", action);
+       Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
 
        if (act) {
                act->activate ();
@@ -2711,3 +2745,11 @@ ARDOUR_UI::TransportControllable::set_id (const string& str)
 {
        _id = str;
 }
+
+void
+ARDOUR_UI::setup_profile ()
+{
+       if (gdk_screen_width() < 1200) {
+               Profile->set_small_screen ();
+       }
+}