FFT analysis: use actual latency
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 74a2f24854dfd300116a622fceeb46f3dd42733e..09912dc95e0d11cdb164485132dd6bfa94497b39 100644 (file)
@@ -79,6 +79,7 @@
 
 #include "widgets/fastmeter.h"
 #include "widgets/prompter.h"
+#include "widgets/tooltips.h"
 
 #include "ardour/ardour.h"
 #include "ardour/audio_backend.h"
@@ -91,6 +92,7 @@
 #include "ardour/filename_extensions.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/ltc_file_reader.h"
+#include "ardour/monitor_control.h"
 #include "ardour/midi_track.h"
 #include "ardour/port.h"
 #include "ardour/plugin_manager.h"
 #include "ardour/session_state_utils.h"
 #include "ardour/session_utils.h"
 #include "ardour/source_factory.h"
-#include "ardour/slave.h"
+#include "ardour/transport_master.h"
+#include "ardour/transport_master_manager.h"
 #include "ardour/system_exec.h"
 #include "ardour/track.h"
 #include "ardour/vca_manager.h"
@@ -165,6 +168,7 @@ typedef uint64_t microseconds_t;
 #include "nsm.h"
 #include "opts.h"
 #include "pingback.h"
+#include "plugin_dspload_window.h"
 #include "processor_box.h"
 #include "public_editor.h"
 #include "rc_option_editor.h"
@@ -184,6 +188,7 @@ typedef uint64_t microseconds_t;
 #include "time_axis_view_item.h"
 #include "time_info_box.h"
 #include "timers.h"
+#include "transport_masters_dialog.h"
 #include "utils.h"
 #include "utils_videotl.h"
 #include "video_server_dialog.h"
@@ -268,14 +273,12 @@ libxml_structured_error_func (void* /* parsing_context*/,
 
 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
-       , session_loaded (false)
        , session_load_in_progress (false)
        , gui_object_state (new GUIObjectState)
        , 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)
-       , global_actions (X_("global"))
        , ignore_dual_punch (false)
        , main_window_visibility (0)
        , editor (0)
@@ -284,7 +287,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , _was_dirty (false)
        , _mixer_on_top (false)
        , _initial_verbose_plugin_scan (false)
-       , first_time_engine_run (true)
+       , _shared_popup_menu (0)
        , secondary_clock_spacer (0)
        , auto_input_button (ArdourButton::led_default_elements)
        , time_info_box (0)
@@ -296,7 +299,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , error_alert_button ( ArdourButton::just_led_default_elements )
        , editor_meter_peak_display()
        , editor_meter(0)
-       , _suspend_editor_meter_callbacks (false)
        , _numpad_locate_happening (false)
        , _session_is_new (false)
        , last_key_press_time (0)
@@ -313,6 +315,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
        , lua_script_window (X_("script-manager"), _("Script Manager"))
        , idleometer (X_("idle-o-meter"), _("Idle'o'Meter"))
+       , plugin_dsp_load_window (X_("plugin-dsp-load"), _("Plugin DSP Load"))
+       , transport_masters_window (X_("transport-masters"), _("Transport Masters"))
        , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
        , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
        , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
@@ -347,7 +351,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
                msg.run ();
                /* configuration was modified, exit immediately */
-               _exit (0);
+               _exit (EXIT_SUCCESS);
        }
 
 
@@ -371,6 +375,32 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        xmlSetGenericErrorFunc (this, libxml_generic_error_func);
        xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
 
+       /* Set this up early */
+
+       ActionManager::init ();
+
+       /* we like keyboards */
+
+       keyboard = new ArdourKeyboard(*this);
+
+       XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
+       if (node) {
+               keyboard->set_state (*node, Stateful::loading_state_version);
+       }
+
+       /* actions do not need to be defined when we load keybindings. They
+        * will be lazily discovered. But bindings do need to exist when we
+        * create windows/tabs with their own binding sets.
+        */
+
+       keyboard->setup_keybindings ();
+
+       if ((global_bindings = Bindings::get_bindings (X_("Global"))) == 0) {
+               error << _("Global keybindings are missing") << endmsg;
+       }
+
+       install_actions ();
+
        UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
        boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
        UIConfiguration::instance().map_parameters (pc);
@@ -434,23 +464,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 
        SessionEvent::create_per_thread_pool ("GUI", 4096);
 
-       /* we like keyboards */
-
-       keyboard = new ArdourKeyboard(*this);
-
-       XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
-       if (node) {
-               keyboard->set_state (*node, Stateful::loading_state_version);
-       }
-
        UIConfiguration::instance().reset_dpi ();
 
        TimeAxisViewItem::set_constant_heights ();
 
-       /* Set this up so that our window proxies can register actions */
-
-       ActionManager::init ();
-
        /* The following must happen after ARDOUR::init() so that Config is set up */
 
        const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
@@ -472,6 +489,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                export_video_dialog.set_state (*ui_xml, 0);
                lua_script_window.set_state (*ui_xml, 0);
                idleometer.set_state (*ui_xml, 0);
+               plugin_dsp_load_window.set_state (*ui_xml, 0);
+               transport_masters_window.set_state (*ui_xml, 0);
        }
 
        /* Separate windows */
@@ -493,6 +512,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        WM::Manager::instance().register_window (&audio_port_matrix);
        WM::Manager::instance().register_window (&midi_port_matrix);
        WM::Manager::instance().register_window (&idleometer);
+       WM::Manager::instance().register_window (&plugin_dsp_load_window);
+       WM::Manager::instance().register_window (&transport_masters_window);
 
        /* do not retain position for add route dialog */
        add_route_dialog.set_state_mask (WindowProxy::Size);
@@ -525,11 +546,12 @@ release software. So, a few guidelines:\n\
    though it may be so, depending on your workflow.\n\
 2) Please wait for a helpful writeup of new features.\n\
 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
-4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
-   making sure to note the product version number as 6.0-pre.\n\
-5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
-6) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
+4) <b>Please do NOT file bugs for this alpha-development versions at this point in time</b>.\n\
+   There is no bug triaging before the initial development concludes and\n\
+   reporting issue for incomplete, ongoing work-in-progress is mostly useless.\n\
+5) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
    can get there directly from within the program via the Help->Chat menu option.\n\
+6) Please <b>DO</b> submit patches for issues after discussing them on IRC.\n\
 \n\
 Full information on all the above can be found on the support page at\n\
 \n\
@@ -555,7 +577,7 @@ ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
 void
 ARDOUR_UI::attach_to_engine ()
 {
-       AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
+       AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this, _1), gui_context());
        ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
 }
 
@@ -570,12 +592,10 @@ ARDOUR_UI::engine_stopped ()
 }
 
 void
-ARDOUR_UI::engine_running ()
+ARDOUR_UI::engine_running (uint32_t cnt)
 {
-       ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
-       if (first_time_engine_run) {
+       if (cnt == 0) {
                post_engine();
-               first_time_engine_run = false;
        }
 
        if (_session) {
@@ -583,7 +603,6 @@ ARDOUR_UI::engine_running ()
        }
        update_disk_space ();
        update_cpu_load ();
-       update_xrun_count ();
        update_sample_rate (AudioEngine::instance()->sample_rate());
        update_timecode_format ();
        update_peak_thread_work ();
@@ -648,8 +667,6 @@ ARDOUR_UI::post_engine ()
        }
 #endif
 
-       ARDOUR::init_post_engine ();
-
        /* connect to important signals */
 
        AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
@@ -722,7 +739,7 @@ ARDOUR_UI::post_engine ()
 
                halt_connection.disconnect ();
                AudioEngine::instance()->stop ();
-               exit (0);
+               exit (EXIT_SUCCESS);
 
        }
 
@@ -748,14 +765,13 @@ ARDOUR_UI::post_engine ()
                output << "      <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
                output << "  </thead>\n  <tbody>" << endl;
 
-               Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
+               ActionManager::get_all_actions (paths, labels, tooltips, keys, actions);
 
                vector<string>::iterator p;
                vector<string>::iterator l;
 
                for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
-                       output << "     <tr><th><kbd class=\"osc\">" << (*p).substr (10, string::npos);
-                       output << "</kbd></th><td>" << *l << "</td></tr>" << endl;
+                       output << " <tr><th><kbd class=\"osc\">" << *p << "</kbd></th><td>" << *l << "</td></tr>" << endl;
                }
                output << "  </tbody>\n  </table>" << endl;
 
@@ -800,7 +816,7 @@ ARDOUR_UI::post_engine ()
 
                halt_connection.disconnect ();
                AudioEngine::instance()->stop ();
-               exit (0);
+               exit (EXIT_SUCCESS);
        }
 
        /* this being a GUI and all, we want peakfiles */
@@ -851,6 +867,7 @@ ARDOUR_UI::~ARDOUR_UI ()
                delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
                delete nsm; nsm = 0;
                delete gui_object_state; gui_object_state = 0;
+               delete _shared_popup_menu ; _shared_popup_menu = 0;
                delete main_window_visibility;
                FastMeter::flush_pattern_cache ();
                ArdourFader::flush_pattern_cache ();
@@ -1244,7 +1261,7 @@ ARDOUR_UI::starting ()
                        c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
 
                        if (d.run () != RESPONSE_OK) {
-                               _exit (0);
+                               _exit (EXIT_SUCCESS);
                        }
                }
 #endif
@@ -1508,8 +1525,6 @@ void
 ARDOUR_UI::every_second ()
 {
        update_cpu_load ();
-       update_xrun_count ();
-       update_buffer_load ();
        update_disk_space ();
        update_timecode_format ();
        update_peak_thread_work ();
@@ -1588,7 +1603,7 @@ ARDOUR_UI::update_sample_rate (samplecnt_t)
 
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
 
-       if (!AudioEngine::instance()->connected()) {
+       if (!AudioEngine::instance()->running()) {
 
                snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
 
@@ -1654,6 +1669,9 @@ ARDOUR_UI::update_format ()
        case MBWF:
                s << _("MBWF");
                break;
+       case FLAC:
+               s << _("FLAC");
+               break;
        }
 
        s << " ";
@@ -1676,29 +1694,33 @@ ARDOUR_UI::update_format ()
 }
 
 void
-ARDOUR_UI::update_xrun_count ()
+ARDOUR_UI::update_cpu_load ()
 {
-       /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
-          should also be changed.
-       */
+       const unsigned int x = _session ? _session->get_xrun_count () : 0;
+       double const c = AudioEngine::instance()->get_dsp_load ();
 
-       if (_session) {
-               const unsigned int x = _session->get_xrun_count ();
-               dsp_load_indicator.set_xrun_count (x);
+       const char* const bg = c > 90 ? " background=\"red\"" : "";
+
+       char buf[64];
+       if (x > 9999) {
+               snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (>10k)", bg, c);
+       } else if (x > 0) {
+               snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (%d)", bg, c, x);
        } else {
-               dsp_load_indicator.set_xrun_count (UINT_MAX);
+               snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span>", bg, c);
        }
-}
 
-void
-ARDOUR_UI::update_cpu_load ()
-{
-       /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
-          should also be changed.
-       */
+       dsp_load_label.set_markup (buf);
 
-       double const c = AudioEngine::instance()->get_dsp_load ();
-       dsp_load_indicator.set_dsp_load (c);
+       if (x > 9999) {
+               snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: >10k\n%s"), c, _("Shift+Click to clear xruns."));
+       } else if (x > 0) {
+               snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: %u\n%s"), c, x, _("Shift+Click to clear xruns."));
+       } else {
+               snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), c);
+       }
+
+       ArdourWidgets::set_tooltip (dsp_load_label, buf);
 }
 
 void
@@ -1714,15 +1736,6 @@ ARDOUR_UI::update_peak_thread_work ()
        }
 }
 
-void
-ARDOUR_UI::update_buffer_load ()
-{
-       uint32_t const playback = _session ? _session->playback_load () : 100;
-       uint32_t const capture = _session ? _session->capture_load () : 100;
-       uint32_t max_load = std::min ( playback, capture );
-       disk_io_indicator.set_disk_io(max_load);
-}
-
 void
 ARDOUR_UI::count_recenabled_streams (Route& route)
 {
@@ -1732,11 +1745,43 @@ ARDOUR_UI::count_recenabled_streams (Route& route)
        }
 }
 
+void
+ARDOUR_UI::format_disk_space_label (float remain_sec)
+{
+       if (remain_sec < 0) {
+               disk_space_label.set_text (_("N/A"));
+               ArdourWidgets::set_tooltip (disk_space_label, _("Unknown"));
+               return;
+       }
+
+       char buf[64];
+
+       int sec = floor (remain_sec);
+       int hrs  = sec / 3600;
+       int mins = (sec / 60) % 60;
+       int secs = sec % 60;
+       snprintf (buf, sizeof(buf), _("%02dh:%02dm:%02ds"), hrs, mins, secs);
+       ArdourWidgets::set_tooltip (disk_space_label, buf);
+
+       if (remain_sec > 86400) {
+               disk_space_label.set_text (_("Rec: >24h"));
+               return;
+       } else if (remain_sec > 32400 /* 9 hours */) {
+               snprintf (buf, sizeof (buf), "Rec: %.0fh", remain_sec / 3600.f);
+       } else if (remain_sec > 5940 /* 99 mins */) {
+               snprintf (buf, sizeof (buf), "Rec: %.1fh", remain_sec / 3600.f);
+       } else {
+               snprintf (buf, sizeof (buf), "Rec: %.0fm", remain_sec / 60.f);
+       }
+       disk_space_label.set_text (buf);
+
+}
+
 void
 ARDOUR_UI::update_disk_space()
 {
        if (_session == 0) {
-               disk_space_indicator.set_available_disk_sec (-1);
+               format_disk_space_label (-1);
                return;
        }
 
@@ -1745,15 +1790,15 @@ ARDOUR_UI::update_disk_space()
 
        if (fr == 0) {
                /* skip update - no SR available */
-               disk_space_indicator.set_available_disk_sec (-1);
+               format_disk_space_label (-1);
                return;
        }
 
        if (!opt_samples) {
                /* Available space is unknown */
-               disk_space_indicator.set_available_disk_sec (-1);
+               format_disk_space_label (-1);
        } else if (opt_samples.get_value_or (0) == max_samplecnt) {
-               disk_space_indicator.set_available_disk_sec (max_samplecnt);
+               format_disk_space_label (max_samplecnt);
        } else {
                rec_enabled_streams = 0;
                _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
@@ -1764,11 +1809,7 @@ ARDOUR_UI::update_disk_space()
                        samples /= rec_enabled_streams;
                }
 
-               int hrs;
-               int mins;
-               int secs;
-
-               disk_space_indicator.set_available_disk_sec (samples / (float)fr);
+               format_disk_space_label (samples / (float)fr);
        }
 
 }
@@ -1780,11 +1821,11 @@ ARDOUR_UI::update_timecode_format ()
 
        if (_session) {
                bool matching;
-               TimecodeSlave* tcslave;
-               SyncSource sync_src = Config->get_sync_source();
+               boost::shared_ptr<TimecodeTransportMaster> tcmaster;
+               boost::shared_ptr<TransportMaster> tm = TransportMasterManager::instance().current();
 
-               if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
-                       matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
+               if ((tm->type() == LTC || tm->type() == MTC) && (tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0) {
+                       matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
                } else {
                        matching = true;
                }
@@ -1837,7 +1878,7 @@ ARDOUR_UI::open_recent_session ()
                                recent_session_dialog.hide();
                                return;
                        } else {
-                               exit (1);
+                               exit (EXIT_FAILURE);
                        }
                }
 
@@ -1865,7 +1906,7 @@ ARDOUR_UI::open_recent_session ()
 bool
 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
 {
-       if (!AudioEngine::instance()->connected()) {
+       if (!AudioEngine::instance()->running()) {
                MessageDialog msg (parent, string_compose (
                                           _("%1 is not connected to any audio backend.\n"
                                           "You cannot open or close sessions in this condition"),
@@ -2089,6 +2130,32 @@ ARDOUR_UI::session_add_audio_route (
        }
 }
 
+void
+ARDOUR_UI::session_add_foldback_bus (uint32_t how_many, string const & name_template)
+{
+       RouteList routes;
+
+       assert (_session);
+
+       try {
+               routes = _session->new_audio_route (2, 2, 0, how_many, name_template, PresentationInfo::FoldbackBus, -1);
+
+               if (routes.size() != how_many) {
+                       error << string_compose (P_("could not create %1 new foldback bus", "could not create %1 new foldback busses", how_many), how_many)
+                             << endmsg;
+               }
+       }
+
+       catch (...) {
+               display_insufficient_ports_message ();
+               return;
+       }
+
+       for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+               (*i)->set_strict_io (true);
+       }
+}
+
 void
 ARDOUR_UI::display_insufficient_ports_message ()
 {
@@ -2274,9 +2341,8 @@ ARDOUR_UI::transport_roll ()
                return;
        }
 
-#if 0
        if (_session->config.get_external_sync()) {
-               switch (Config->get_sync_source()) {
+               switch (TransportMasterManager::instance().current()->type()) {
                case Engine:
                        break;
                default:
@@ -2284,7 +2350,6 @@ ARDOUR_UI::transport_roll ()
                        return;
                }
        }
-#endif
 
        bool rolling = _session->transport_rolling();
 
@@ -2338,7 +2403,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
        }
 
        if (_session->config.get_external_sync()) {
-               switch (Config->get_sync_source()) {
+               switch (TransportMasterManager::instance().current()->type()) {
                case Engine:
                        break;
                default:
@@ -2582,9 +2647,6 @@ ARDOUR_UI::blink_handler (bool blink_on)
        solo_blink (blink_on);
        audition_blink (blink_on);
        feedback_blink (blink_on);
-
-       dsp_load_indicator.blink(blink_on);
-       disk_space_indicator.blink(blink_on);
 }
 
 void
@@ -2653,13 +2715,13 @@ ARDOUR_UI::save_session_as ()
                                        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\
+If you still wish to proceed, please use the\n\n\
 \"Don't save now\" option."), PROGRAM_NAME));
                                        pop_back_splash(msg);
                                        msg.run ();
                                        return;
                                }
-                               // no break
+                               /* fall through */
                        case 0:
                                _session->remove_pending_capture_state ();
                                break;
@@ -2849,13 +2911,13 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
                                        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\
+If you still wish to proceed, please use the\n\n\
 \"Don't save now\" option."), PROGRAM_NAME));
                                        pop_back_splash(msg);
                                        msg.run ();
                                        return;
                                }
-                               // no break
+                               /* fall through */
                        case 0:
                                _session->remove_pending_capture_state ();
                                break;
@@ -3180,7 +3242,7 @@ ARDOUR_UI::load_from_application_api (const std::string& path)
                ARDOUR_COMMAND_LINE::session_name = "";
 
                if (get_session_parameters (true, false)) {
-                       exit (1);
+                       exit (EXIT_FAILURE);
                }
        }
 }
@@ -3421,12 +3483,12 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
 
                        if (ret == -2) {
                                /* not connected to the AudioEngine, so quit to avoid an infinite loop */
-                               exit (1);
+                               exit (EXIT_FAILURE);
                        }
 
                        if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
                                _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
-                               exit (1);
+                               exit (EXIT_FAILURE);
                        }
 
                        /* clear this to avoid endless attempts to load the
@@ -3456,7 +3518,7 @@ ARDOUR_UI::close_session()
        ARDOUR_COMMAND_LINE::session_name = "";
 
        if (get_session_parameters (true, false)) {
-               exit (1);
+               exit (EXIT_FAILURE);
        }
 }
 
@@ -3493,8 +3555,6 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
                }
        }
 
-       session_loaded = false;
-
        loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
 
        try {
@@ -3522,7 +3582,7 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 
                switch (response) {
                case RESPONSE_CANCEL:
-                       exit (1);
+                       exit (EXIT_FAILURE);
                default:
                        break;
                }
@@ -3604,8 +3664,6 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 
        set_session (new_session);
 
-       session_loaded = true;
-
        if (_session) {
                _session->set_clean ();
        }
@@ -3649,7 +3707,6 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
        Session *new_session;
        int x;
 
-       session_loaded = false;
        x = unload_session ();
 
        if (x < 0) {
@@ -3714,8 +3771,6 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
 
        set_session (new_session);
 
-       session_loaded = true;
-
        new_session->save_state(new_session->name());
 
        return 0;
@@ -3866,13 +3921,7 @@ ARDOUR_UI::launch_chat ()
 
        switch (dialog.run()) {
        case RESPONSE_OK:
-#ifdef __APPLE__
-               open_uri("http://webchat.freenode.net/?channels=ardour-osx");
-#elif defined PLATFORM_WINDOWS
-               open_uri("http://webchat.freenode.net/?channels=ardour-windows");
-#else
                open_uri("http://webchat.freenode.net/?channels=ardour");
-#endif
                break;
        default:
                break;
@@ -4148,17 +4197,14 @@ Clean-up will move all unused files to a \"dead\" location."));
        default:
                return;
        }
+       checker.hide();
 
        ARDOUR::CleanupReport rep;
 
        editor->prepare_for_cleanup ();
 
        /* do not allow flush until a session is reloaded */
-
-       Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
-       if (act) {
-               act->set_sensitive (false);
-       }
+       ActionManager::get_action (X_("Main"), X_("FlushWastebasket"))->set_sensitive (false);
 
        if (_session->cleanup_sources (rep)) {
                editor->finish_cleanup ();
@@ -4167,7 +4213,6 @@ Clean-up will move all unused files to a \"dead\" location."));
 
        editor->finish_cleanup ();
 
-       checker.hide();
        display_cleanup_results (rep, _("Cleaned Files"), false);
 }
 
@@ -4305,6 +4350,19 @@ ARDOUR_UI::add_route_dialog_response (int r)
                return;
        }
 
+       if (!AudioEngine::instance()->running ()) {
+               switch (r) {
+                       case AddRouteDialog::Add:
+                       case AddRouteDialog::AddAndClose:
+                               break;
+                       default:
+                               return;
+               }
+               add_route_dialog->ArdourDialog::on_response (r);
+               ARDOUR_UI_UTILS::engine_is_running ();
+               return;
+       }
+
        int count;
 
        switch (r) {
@@ -4379,6 +4437,9 @@ ARDOUR_UI::add_route_dialog_response (int r)
        case AddRouteDialog::VCAMaster:
                _session->vca_manager().create_vca (count, name_template);
                break;
+       case AddRouteDialog::FoldbackBus:
+               session_add_foldback_bus (count, name_template);
+               break;
        }
 }
 
@@ -4872,10 +4933,6 @@ ARDOUR_UI::xrun_handler (samplepos_t where)
 
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
 
-       if (_session && _session->actively_recording()) {
-               dsp_load_indicator.set_xrun_while_recording();
-       }
-
        if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
                create_xrun_marker(where);
        }
@@ -5357,53 +5414,6 @@ ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_pat
        msg.run ();
 }
 
-void
-ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
-{
-       using namespace Menu_Helpers;
-
-       items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
-       RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
-       i->set_active (editor_meter->meter_type () == type);
-}
-
-void
-ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
-{
-       using namespace Gtk::Menu_Helpers;
-
-       Gtk::Menu* m = manage (new Menu);
-       MenuList& items = m->items ();
-
-       RadioMenuItem::Group group;
-
-       _suspend_editor_meter_callbacks = true;
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
-       add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
-
-       m->popup (ev->button, ev->time);
-       _suspend_editor_meter_callbacks = false;
-}
-
-bool
-ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
-{
-       if (ev->button == 3 && editor_meter) {
-               popup_editor_meter_menu (ev);
-               return true;
-       }
-       return false;
-}
-
 void
 ARDOUR_UI::reset_peak_display ()
 {
@@ -5500,16 +5510,16 @@ ARDOUR_UI::transport_numpad_event (int num)
                _pending_locate_num = _pending_locate_num*10 + num;
        } else {
                switch (num) {
-                       case 0:  toggle_roll(false, false);             break;
-                       case 1:  transport_rewind(1);                           break;
-                       case 2:  transport_forward(1);                          break;
-                       case 3:  transport_record(true);                        break;
-                       case 4:  toggle_session_auto_loop();            break;
-                       case 5:  transport_record(false); toggle_session_auto_loop();   break;
-                       case 6:  toggle_punch();                                        break;
-                       case 7:  toggle_click();                                break;
-                       case 8:  toggle_auto_return();                  break;
-                       case 9:  toggle_follow_edits();         break;
+                       case 0: toggle_roll(false, false);                           break;
+                       case 1: transport_rewind(1);                                 break;
+                       case 2: transport_forward(1);                                break;
+                       case 3: transport_record(true);                              break;
+                       case 4: toggle_session_auto_loop();                          break;
+                       case 5: transport_record(false); toggle_session_auto_loop(); break;
+                       case 6: toggle_punch();                                      break;
+                       case 7: toggle_click();                                      break;
+                       case 8: toggle_auto_return();                                break;
+                       case 9: toggle_follow_edits();                               break;
                }
        }
 }
@@ -5567,7 +5577,7 @@ ARDOUR_UI::audioengine_became_silent ()
        case Gtk::RESPONSE_NO:
                /* save and quit */
                save_state_canfail ("");
-               exit (0);
+               exit (EXIT_SUCCESS);
                break;
 
        case Gtk::RESPONSE_CANCEL:
@@ -5804,7 +5814,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
                        }
                }
 
-               DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+               DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
 
                if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
                        DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
@@ -5854,7 +5864,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
                        }
                }
 
-               DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+               DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
 
                if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
                        DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
@@ -5866,14 +5876,6 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
        return true;
 }
 
-void
-ARDOUR_UI::load_bindings ()
-{
-       if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
-               error << _("Global keybindings are missing") << endmsg;
-       }
-}
-
 void
 ARDOUR_UI::cancel_solo ()
 {
@@ -5933,3 +5935,53 @@ ARDOUR_UI::reset_focus (Gtk::Widget* w)
        gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
 
 }
+
+void
+ARDOUR_UI::monitor_dim_all ()
+{
+       boost::shared_ptr<Route> mon = _session->monitor_out ();
+       if (!mon) {
+               return;
+       }
+       boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
+
+       Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-dim-all");
+       _monitor->set_dim_all (tact->get_active());
+}
+
+void
+ARDOUR_UI::monitor_cut_all ()
+{
+       boost::shared_ptr<Route> mon = _session->monitor_out ();
+       if (!mon) {
+               return;
+       }
+       boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
+
+       Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-cut-all");
+       _monitor->set_cut_all (tact->get_active());
+}
+
+void
+ARDOUR_UI::monitor_mono ()
+{
+       boost::shared_ptr<Route> mon = _session->monitor_out ();
+       if (!mon) {
+               return;
+       }
+       boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
+
+       Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-mono");
+       _monitor->set_mono (tact->get_active());
+}
+
+Gtk::Menu*
+ARDOUR_UI::shared_popup_menu ()
+{
+       ENSURE_GUI_THREAD (*this, &ARDOUR_UI::shared_popup_menu, ignored);
+
+       assert (!_shared_popup_menu || !_shared_popup_menu->is_visible());
+       delete _shared_popup_menu;
+       _shared_popup_menu = new Gtk::Menu;
+       return _shared_popup_menu;
+}