tracks build ... backends are hard-coded
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 307a8ba7f25e1137a8d49d06f8cccb256ea40e32..0d646c8add46e24811c95fec8035b2d42e948632 100644 (file)
@@ -97,6 +97,7 @@
 typedef uint64_t microseconds_t;
 
 #include "about.h"
+#include "editing.h"
 #include "actions.h"
 #include "add_route_dialog.h"
 #include "ambiguous_file_dialog.h"
@@ -128,6 +129,7 @@ typedef uint64_t microseconds_t;
 #include "rc_option_editor.h"
 #include "route_time_axis.h"
 #include "route_params_ui.h"
+#include "save_as_dialog.h"
 #include "session_dialog.h"
 #include "session_metadata_dialog.h"
 #include "session_option_editor.h"
@@ -151,12 +153,14 @@ using namespace PBD;
 using namespace Gtkmm2ext;
 using namespace Gtk;
 using namespace std;
+using namespace Editing;
 
 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
 
 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
 sigc::signal<void>      ARDOUR_UI::CloseAllDialogs;
 
+float ARDOUR_UI::ui_scale = 1.0;
 
 static bool
 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
@@ -177,30 +181,23 @@ ask_about_configuration_copy (string const & old_dir, string const & new_dir, in
        return (msg.run() == Gtk::RESPONSE_YES);
 }
 
-ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
+ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir, UIConfiguration* uic)
 
        : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
-       , ui_config (new UIConfiguration)
+       , ui_config (uic->post_gui_init ())
+       , session_loaded (false)
        , gui_object_state (new GUIObjectState)
-
-       , primary_clock (new MainClock (X_("primary"), false, X_("transport"), true, true, true, false, true))
-       , secondary_clock (new MainClock (X_("secondary"), false, X_("secondary"), true, true, false, false, true))
-         
-         /* big clock */
-
+       , primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
+       , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
        , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
        , video_timeline(0)
-
-         /* start of private members */
+       , ignore_dual_punch (false)
        , editor (0)
        , mixer (0)
        , nsm (0)
        , _was_dirty (false)
        , _mixer_on_top (false)
        , first_time_engine_run (true)
-
-         /* transport */
-
        , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
        , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
        , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
@@ -208,19 +205,22 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
        , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
        , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
-
        , auto_return_button (ArdourButton::led_default_elements)
        , follow_edits_button (ArdourButton::led_default_elements)
        , auto_input_button (ArdourButton::led_default_elements)
-
        , auditioning_alert_button (_("Audition"))
        , solo_alert_button (_("Solo"))
        , feedback_alert_button (_("Feedback"))
        , error_alert_button ( ArdourButton::just_led_default_elements )
-
        , editor_meter(0)
        , editor_meter_peak_display()
-
+       , session_selector_window (0)
+       , open_session_selector (0)
+       , _numpad_locate_happening (false)
+       , _session_is_new (false)
+       , last_key_press_time (0)
+       , save_as_dialog (0)
+       , meterbridge (0)
        , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
        , key_editor (X_("key-editor"), _("Key Bindings"))
        , rc_option_editor (X_("rc-options-editor"), _("Preferences"))
@@ -236,12 +236,17 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
        , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
        , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
-
+       , video_server_process (0)
+       , splash (0)
+       , have_configure_timeout (false)
+       , last_configure_time (0)
+       , last_peak_grab (0)
+       , have_disk_speed_dialog_displayed (false)
        , _status_bar_visibility (X_("status-bar"))
        , _feedback_exists (false)
        , _log_not_acknowledged (LogLevelNone)
 {
-       Gtkmm2ext::init(localedir);
+       Gtkmm2ext::init (localedir);
 
        if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
                MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
@@ -249,12 +254,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                /* configuration was modified, exit immediately */
                _exit (0);
        }
-
        
-       splash = 0;
-
-       _numpad_locate_happening = false;
-
        if (theArdourUI == 0) {
                theArdourUI = this;
        }
@@ -263,20 +263,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
        ui_config->map_parameters (pc);
 
-       editor = 0;
-       mixer = 0;
-       meterbridge = 0;
-       editor = 0;
-       _session_is_new = false;
-       session_selector_window = 0;
-       last_key_press_time = 0;
-       video_server_process = 0;
-       open_session_selector = 0;
-       have_configure_timeout = false;
-       have_disk_speed_dialog_displayed = false;
-       session_loaded = false;
-       ignore_dual_punch = false;
-
        roll_button.set_controllable (roll_controllable);
        stop_button.set_controllable (stop_controllable);
        goto_start_button.set_controllable (goto_start_controllable);
@@ -294,9 +280,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        rec_button.set_name ("transport recenable button");
        midi_panic_button.set_name ("transport button");
 
-       last_configure_time= 0;
-       last_peak_grab = 0;
-
        ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
        ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
 
@@ -452,8 +435,12 @@ ARDOUR_UI::engine_running ()
                first_time_engine_run = false;
        } 
        
+       if (_session) {
+               _session->reset_xrun_count ();
+       }
        update_disk_space ();
        update_cpu_load ();
+       update_xrun_count ();
        update_sample_rate (AudioEngine::instance()->sample_rate());
        update_timecode_format ();
 }
@@ -817,13 +804,16 @@ ARDOUR_UI::starting ()
        if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
                nsm = new NSM_Client;
                if (!nsm->init (nsm_url)) {
-                       /* TODO this needs fixing!
+                       /* the ardour executable may have different names:
+                        *
                         * waf's obj.target for distro versions: eg ardour4, ardourvst4
                         * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
                         * argv[0] does not apply since we need the wrapper-script (not the binary itself)
-                        * No idea how to address all these.
+                        *
+                        * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
                         */
-                       nsm->announce (PROGRAM_NAME, ":dirty:", "ardour4");
+                       const char *process_name = g_getenv ("ARDOUR_SELF");
+                       nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour4");
 
                        unsigned int i = 0;
                        // wait for announce reply from nsm server
@@ -1197,6 +1187,7 @@ void
 ARDOUR_UI::every_second ()
 {
        update_cpu_load ();
+       update_xrun_count ();
        update_buffer_load ();
        update_disk_space ();
        update_timecode_format ();
@@ -1357,6 +1348,29 @@ ARDOUR_UI::update_format ()
        format_label.set_markup (s.str ());
 }
 
+void
+ARDOUR_UI::update_xrun_count ()
+{
+       char buf[64];
+
+       /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
+          should also be changed.
+       */
+
+       if (_session) {
+               const unsigned int x = _session->get_xrun_count ();
+               if (x > 9999) {
+                       snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">&gt;10K</span>"), X_("red"));
+               } else {
+                       snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">%u</span>"), x > 0 ? X_("red") : X_("green"), x);
+               }
+       } else {
+               snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">?</span>"), X_("yellow"));
+       }
+       xrun_label.set_markup (buf);
+       set_tip (xrun_label, _("Audio dropouts. Shift+click to reset"));
+}
+
 void
 ARDOUR_UI::update_cpu_load ()
 {
@@ -2090,7 +2104,6 @@ ARDOUR_UI::get_smart_mode() const
 void
 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
 {
-
        if (!_session) {
                return;
        }
@@ -2353,7 +2366,7 @@ ARDOUR_UI::update_clocks ()
        if (!_session) return;
 
        if (editor && !editor->dragging_playhead()) {
-               Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
+               Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
        }
 }
 
@@ -2373,6 +2386,103 @@ ARDOUR_UI::stop_clocking ()
        clock_signal_connection.disconnect ();
 }
 
+bool
+ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
+{
+       char buf[256];
+
+       snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
+
+       label->set_text (buf);
+       bar->set_fraction (fraction);
+
+       /* process events, redraws, etc. */
+       
+       while (gtk_events_pending()) {
+               gtk_main_iteration ();
+       }
+
+       return true; /* continue with save-as */
+}
+
+void
+ARDOUR_UI::save_session_as ()
+{
+       if (!_session) {
+               return;
+       }
+
+       if (!save_as_dialog) {
+               save_as_dialog = new SaveAsDialog;
+       } else {
+               save_as_dialog->clear_name ();
+       }
+
+       int response = save_as_dialog->run ();
+
+       save_as_dialog->hide ();
+       
+       switch (response) {
+       case Gtk::RESPONSE_OK:
+               break;
+       default:
+               return;
+       }
+       
+       
+       Session::SaveAs sa;
+
+       sa.new_parent_folder = save_as_dialog->new_parent_folder ();
+       sa.new_name = save_as_dialog->new_name ();
+       sa.switch_to = save_as_dialog->switch_to();
+       sa.copy_media = save_as_dialog->copy_media();
+       sa.copy_external = save_as_dialog->copy_external();
+       sa.include_media = save_as_dialog->include_media ();
+
+       /* Only bother with a progress dialog if we're going to copy
+          media into the save-as target. Without that choice, this
+          will be very fast because we're only talking about a few kB's to
+          perhaps a couple of MB's of data.
+       */
+       
+       ArdourDialog progress_dialog (_("Save As"), true);
+
+       if (sa.include_media && sa.copy_media) {
+               
+               Gtk::Label label;
+               Gtk::ProgressBar progress_bar;
+               
+               progress_dialog.get_vbox()->pack_start (label);
+               progress_dialog.get_vbox()->pack_start (progress_bar);
+               label.show ();
+               progress_bar.show ();
+
+               /* this signal will be emitted from within this, the calling thread,
+                * after every file is copied. It provides information on percentage
+                * complete (in terms of total data to copy), the number of files
+                * copied so far, and the total number to copy.
+                */
+               
+               ScopedConnection c;
+               
+               sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
+               
+               progress_dialog.show_all ();
+               progress_dialog.present ();
+       }
+       
+       if (_session->save_as (sa)) {
+               /* ERROR MESSAGE */
+               MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
+               msg.run ();
+       }
+
+       if (!sa.include_media) {
+               unload_session (false);
+               load_session (sa.final_session_folder_name, sa.new_name);
+       }
+}
+
 /** Ask the user for the name of a new snapshot and then take it.
  */
 
@@ -4007,7 +4117,10 @@ ARDOUR_UI::keyboard_settings () const
 void
 ARDOUR_UI::create_xrun_marker (framepos_t where)
 {
-       editor->mouse_add_new_marker (where, false, true);
+       if (_session) {
+               Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
+               _session->locations()->add (location);
+       }
 }
 
 void
@@ -4329,13 +4442,13 @@ void
 ARDOUR_UI::update_transport_clocks (framepos_t pos)
 {
        if (ui_config->get_primary_clock_delta_edit_cursor()) {
-               primary_clock->set (pos, false, editor->get_preferred_edit_position());
+               primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
        } else {
                primary_clock->set (pos);
        }
 
        if (ui_config->get_secondary_clock_delta_edit_cursor()) {
-               secondary_clock->set (pos, false, editor->get_preferred_edit_position());
+               secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
        } else {
                secondary_clock->set (pos);
        }
@@ -4752,3 +4865,9 @@ ARDOUR_UI::audioengine_became_silent ()
                break;
        }
 }
+       
+void
+ARDOUR_UI::hide_application ()
+{
+    Application::instance ()-> hide ();
+}