Skip script-setup if there are no parameters (and name is unique)
[ardour.git] / gtk2_ardour / ardour_ui.cc
index d9ea44c3256821b4cf83f7c54dca3c7936be6c32..e8c794f85e85f87309decfbca78fcfb41d8acc74 100644 (file)
 #include "pbd/memento_command.h"
 #include "pbd/openuri.h"
 #include "pbd/stl_delete.h"
+#include "pbd/types_convert.h"
 #include "pbd/file_utils.h"
 #include "pbd/localtime_r.h"
 #include "pbd/pthread_utils.h"
 #include "pbd/replace_all.h"
+#include "pbd/scoped_file_descriptor.h"
 #include "pbd/xml++.h"
 
 #include "gtkmm2ext/application.h"
@@ -93,6 +95,7 @@
 #include "ardour/profile.h"
 #include "ardour/recent_sessions.h"
 #include "ardour/record_enable_control.h"
+#include "ardour/revision.h"
 #include "ardour/session_directory.h"
 #include "ardour/session_route.h"
 #include "ardour/session_state_utils.h"
@@ -124,6 +127,7 @@ typedef uint64_t microseconds_t;
 
 #include "about.h"
 #include "editing.h"
+#include "enums_convert.h"
 #include "actions.h"
 #include "add_route_dialog.h"
 #include "ambiguous_file_dialog.h"
@@ -141,6 +145,7 @@ typedef uint64_t microseconds_t;
 #include "global_port_matrix.h"
 #include "gui_object.h"
 #include "gui_thread.h"
+#include "idleometer.h"
 #include "keyboard.h"
 #include "keyeditor.h"
 #include "location_ui.h"
@@ -151,6 +156,7 @@ typedef uint64_t microseconds_t;
 #include "missing_plugin_dialog.h"
 #include "mixer_ui.h"
 #include "meterbridge.h"
+#include "meter_patterns.h"
 #include "mouse_cursors.h"
 #include "nsm.h"
 #include "opts.h"
@@ -290,6 +296,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , error_alert_button ( ArdourButton::just_led_default_elements )
        , editor_meter(0)
        , editor_meter_peak_display()
+       , _suspend_editor_meter_callbacks (false)
        , _numpad_locate_happening (false)
        , _session_is_new (false)
        , last_key_press_time (0)
@@ -305,6 +312,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
        , 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"))
        , 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))
@@ -331,6 +339,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        UIConfiguration::instance().post_gui_init ();
 
        if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
+               {
+                       /* "touch" the been-here-before path now that config has been migrated */
+                       PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
+               }
                MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
                msg.run ();
                /* configuration was modified, exit immediately */
@@ -472,6 +484,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                midi_port_matrix.set_state (*ui_xml, 0);
                export_video_dialog.set_state (*ui_xml, 0);
                lua_script_window.set_state (*ui_xml, 0);
+               idleometer.set_state (*ui_xml, 0);
        }
 
        /* Separate windows */
@@ -491,6 +504,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        WM::Manager::instance().register_window (&big_clock_window);
        WM::Manager::instance().register_window (&audio_port_matrix);
        WM::Manager::instance().register_window (&midi_port_matrix);
+       WM::Manager::instance().register_window (&idleometer);
 
        /* do not retain position for add route dialog */
        add_route_dialog.set_state_mask (WindowProxy::Size);
@@ -681,20 +695,30 @@ ARDOUR_UI::post_engine ()
                vector<string> tooltips;
                vector<string> keys;
                vector<Glib::RefPtr<Gtk::Action> > actions;
+               string ver_in = revision;
+               string ver = ver_in.substr(0, ver_in.find("-"));
+
+               cout << "\n<h2>Menu actions</h2>" << endl;
+               cout << "<!-- created by running " << PROGRAM_NAME << " -b -->" << endl;
+               cout << "<p>\n  Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl;
+               cout << "  surfaces or scripts.\n</p>\n" << endl;
+               cout << "<p>\n  The list below shows all available values of <em>action-name</em> as of" << endl;
+               cout << "  " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl;
+               cout << "  time by running " << PROGRAM_NAME << " with the -b flag.\n</p>\n" << endl;
+               cout << "<table class=\"dl\">\n  <thead>" << endl;
+               cout << "      <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
+               cout << "  </thead>\n  <tbody>" << endl;
 
                Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
 
-               vector<string>::iterator k;
                vector<string>::iterator p;
+               vector<string>::iterator l;
 
-               for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
-
-                       if ((*k).empty()) {
-                               cout << *p << endl;
-                       } else {
-                               cout << *p << " => " << *k << endl;
-                       }
+               for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
+                       cout << "       <tr><th><kbd class=\"osc\">" << (*p).substr (9, string::npos);
+                       cout << "</kbd></th><td>" << *l << "</td></tr>" << endl;
                }
+               cout << "  </tbody>\n  </table class=\"dl\">" << endl;
 
                halt_connection.disconnect ();
                AudioEngine::instance()->stop ();
@@ -746,6 +770,7 @@ ARDOUR_UI::~ARDOUR_UI ()
                delete luawindow; luawindow = 0;
                delete editor; editor = 0;
                delete mixer; mixer = 0;
+               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 main_window_visibility;
@@ -807,31 +832,31 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
 void
 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
 {
-       XMLProperty const * prop;
+       std::string str;
 
-       if ((prop = node.property ("roll")) != 0) {
-               roll_controllable->set_id (prop->value());
+       if (node.get_property ("roll", str)){
+               roll_controllable->set_id (str);
        }
-       if ((prop = node.property ("stop")) != 0) {
-               stop_controllable->set_id (prop->value());
+       if (node.get_property ("stop", str)) {
+               stop_controllable->set_id (str);
        }
-       if ((prop = node.property ("goto-start")) != 0) {
-               goto_start_controllable->set_id (prop->value());
+       if (node.get_property ("goto-start", str)) {
+               goto_start_controllable->set_id (str);
        }
-       if ((prop = node.property ("goto-end")) != 0) {
-               goto_end_controllable->set_id (prop->value());
+       if (node.get_property ("goto-end", str)) {
+               goto_end_controllable->set_id (str);
        }
-       if ((prop = node.property ("auto-loop")) != 0) {
-               auto_loop_controllable->set_id (prop->value());
+       if (node.get_property ("auto-loop", str)) {
+               auto_loop_controllable->set_id (str);
        }
-       if ((prop = node.property ("play-selection")) != 0) {
-               play_selection_controllable->set_id (prop->value());
+       if (node.get_property ("play-selection", str)) {
+               play_selection_controllable->set_id (str);
        }
-       if ((prop = node.property ("rec")) != 0) {
-               rec_controllable->set_id (prop->value());
+       if (node.get_property ("rec", str)) {
+               rec_controllable->set_id (str);
        }
-       if ((prop = node.property ("shuttle")) != 0) {
-               shuttle_box.controllable()->set_id (prop->value());
+       if (node.get_property ("shuttle", str)) {
+               shuttle_box.controllable()->set_id (str);
        }
 }
 
@@ -839,24 +864,15 @@ XMLNode&
 ARDOUR_UI::get_transport_controllable_state ()
 {
        XMLNode* node = new XMLNode(X_("TransportControllables"));
-       char buf[64];
 
-       roll_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("roll"), buf);
-       stop_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("stop"), buf);
-       goto_start_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("goto_start"), buf);
-       goto_end_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("goto_end"), buf);
-       auto_loop_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("auto_loop"), buf);
-       play_selection_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("play_selection"), buf);
-       rec_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("rec"), buf);
-       shuttle_box.controllable()->id().print (buf, sizeof (buf));
-       node->add_property (X_("shuttle"), buf);
+       node->set_property (X_("roll"), roll_controllable->id());
+       node->set_property (X_("stop"), stop_controllable->id());
+       node->set_property (X_("goto_start"), goto_start_controllable->id());
+       node->set_property (X_("goto_end"), goto_end_controllable->id());
+       node->set_property (X_("auto_loop"), auto_loop_controllable->id());
+       node->set_property (X_("play_selection"), play_selection_controllable->id());
+       node->set_property (X_("rec"), rec_controllable->id());
+       node->set_property (X_("shuttle"), shuttle_box.controllable()->id());
 
        return *node;
 }
@@ -1939,15 +1955,18 @@ ARDOUR_UI::session_add_mixed_track (
                Plugin::PresetRecord* pset,
                ARDOUR::PresentationInfo::order_t order)
 {
-       list<boost::shared_ptr<MidiTrack> > tracks;
-
        if (_session == 0) {
                warning << _("You cannot add a track without a session already loaded.") << endmsg;
                return;
        }
 
+       if (Profile->get_mixbus ()) {
+               strict_io = true;
+       }
+
        try {
-               tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
+               list<boost::shared_ptr<MidiTrack> > tracks;
+               tracks = _session->new_midi_track (input, output, strict_io, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
 
                if (tracks.size() != how_many) {
                        error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
@@ -1958,12 +1977,6 @@ ARDOUR_UI::session_add_mixed_track (
                display_insufficient_ports_message ();
                return;
        }
-
-       if (strict_io) {
-               for (list<boost::shared_ptr<MidiTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
-                       (*i)->set_strict_io (true);
-               }
-       }
 }
 
 void
@@ -1976,16 +1989,18 @@ ARDOUR_UI::session_add_midi_bus (
                Plugin::PresetRecord* pset,
                ARDOUR::PresentationInfo::order_t order)
 {
-       RouteList routes;
-
        if (_session == 0) {
                warning << _("You cannot add a track without a session already loaded.") << endmsg;
                return;
        }
 
-       try {
+       if (Profile->get_mixbus ()) {
+               strict_io = true;
+       }
 
-               routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order);
+       try {
+               RouteList routes;
+               routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, instrument, pset, PresentationInfo::MidiBus, order);
                if (routes.size() != how_many) {
                        error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
                }
@@ -1995,12 +2010,6 @@ ARDOUR_UI::session_add_midi_bus (
                display_insufficient_ports_message ();
                return;
        }
-
-       if (strict_io) {
-               for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
-                       (*i)->set_strict_io (true);
-               }
-       }
 }
 
 void
@@ -2458,6 +2467,15 @@ ARDOUR_UI::transport_rec_preroll ()
        editor->rec_with_preroll ();
 }
 
+void
+ARDOUR_UI::transport_rec_count_in ()
+{
+       if (!_session) {
+               return;
+       }
+       editor->rec_with_count_in ();
+}
+
 void
 ARDOUR_UI::transport_rewind (int option)
 {
@@ -2602,11 +2620,15 @@ void
 ARDOUR_UI::blink_handler (bool blink_on)
 {
        transport_rec_enable_blink (blink_on);
-       solo_blink (blink_on);
        sync_blink (blink_on);
+
+       if (!UIConfiguration::instance().get_blink_alert_indicators()) {
+               blink_on = true;
+       }
+       error_blink (blink_on);
+       solo_blink (blink_on);
        audition_blink (blink_on);
        feedback_blink (blink_on);
-       error_blink (blink_on);
 }
 
 void
@@ -2695,16 +2717,17 @@ ARDOUR_UI::save_session_as ()
        */
 
        ArdourDialog progress_dialog (_("Save As"), true);
+       ScopedConnection c;
 
        if (sa.include_media && sa.copy_media) {
 
-               Gtk::Label label;
-               Gtk::ProgressBar progress_bar;
+               Gtk::Label* label = manage (new Gtk::Label());
+               Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
 
-               progress_dialog.get_vbox()->pack_start (label);
-               progress_dialog.get_vbox()->pack_start (progress_bar);
-               label.show ();
-               progress_bar.show ();
+               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
@@ -2712,9 +2735,7 @@ ARDOUR_UI::save_session_as ()
                 * 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));
+               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 ();
@@ -2726,9 +2747,18 @@ ARDOUR_UI::save_session_as ()
                msg.run ();
        }
 
-       if (!sa.include_media) {
+       /* the logic here may seem odd: why isn't the condition sa.switch_to ?
+        * the trick is this: if the new session was copy with media included,
+        * then Session::save_as() will have already done a neat trick to avoid
+        * us having to unload and load the new state. But if the media was not
+        * included, then this is required (it avoids us having to otherwise
+        * drop all references to media (sources).
+        */
+
+       if (!sa.include_media && sa.switch_to) {
                unload_session (false);
                load_session (sa.final_session_folder_name, sa.new_name);
+               hide_splash ();
        }
 }
 
@@ -3159,7 +3189,7 @@ void
 ARDOUR_UI::load_from_application_api (const std::string& path)
 {
        /* OS X El Capitan (and probably later) now somehow passes the command
-          line arguments to an app via the openFile delegate protocol. Ardour 
+          line arguments to an app via the openFile delegate protocol. Ardour
           already does its own command line processing, and having both
           pathways active causes crashes. So, if the command line was already
           set, do nothing here.
@@ -3711,8 +3741,8 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
        /* Put the playhead at 0 and scroll fully left */
        n = new_session->instant_xml (X_("Editor"));
        if (n) {
-               n->add_property (X_("playhead"), X_("0"));
-               n->add_property (X_("left-frame"), X_("0"));
+               n->set_property (X_("playhead"), X_("0"));
+               n->set_property (X_("left-frame"), X_("0"));
        }
 
        set_session (new_session);
@@ -4238,89 +4268,6 @@ ARDOUR_UI::add_route_dialog_finished (int r)
        }
 }
 
-void
-ARDOUR_UI::add_lua_script ()
-{
-       if (!_session) {
-               return;
-       }
-
-       LuaScriptInfoPtr spi;
-       ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
-       switch (ss.run ()) {
-               case Gtk::RESPONSE_ACCEPT:
-                       spi = ss.script();
-                       break;
-               default:
-                       return;
-       }
-       ss.hide();
-
-       std::string script = "";
-
-       try {
-               script = Glib::file_get_contents (spi->path);
-       } catch (Glib::FileError e) {
-               string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
-               MessageDialog am (msg);
-               am.run ();
-               return;
-       }
-
-       LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
-       std::vector<std::string> reg = _session->registered_lua_functions ();
-
-       ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
-       switch (spd.run ()) {
-               case Gtk::RESPONSE_ACCEPT:
-                       break;
-               default:
-                       return;
-       }
-
-       try {
-               _session->register_lua_function (spd.name(), script, lsp);
-       } catch (luabridge::LuaException const& e) {
-               string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
-               MessageDialog am (msg);
-               am.run ();
-       } catch (SessionException e) {
-               string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
-               MessageDialog am (msg);
-               am.run ();
-       }
-}
-
-void
-ARDOUR_UI::remove_lua_script ()
-{
-       if (!_session) {
-               return;
-       }
-       if (_session->registered_lua_function_count () ==  0) {
-               string msg = _("There are no active Lua session scripts present in this session.");
-               MessageDialog am (msg);
-               am.run ();
-               return;
-       }
-
-       std::vector<std::string> reg = _session->registered_lua_functions ();
-       SessionScriptManager sm ("Remove Lua Session Script", reg);
-       switch (sm.run ()) {
-               case Gtk::RESPONSE_ACCEPT:
-                       break;
-               default:
-                       return;
-       }
-       try {
-               _session->unregister_lua_function (sm.name());
-       } catch (luabridge::LuaException const& e) {
-               string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
-               MessageDialog am (msg);
-               am.run ();
-       }
-}
-
 void
 ARDOUR_UI::stop_video_server (bool ask_confirm)
 {
@@ -4440,9 +4387,8 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
                if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
                        Config->set_video_advanced_setup(false);
                } else {
-                       std::ostringstream osstream;
-                       osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
-                       Config->set_video_server_url(osstream.str());
+                       std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
+                       Config->set_video_server_url(url_str);
                        Config->set_video_server_docroot(icsd_docroot);
                        Config->set_video_advanced_setup(true);
                }
@@ -4574,11 +4520,11 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
 
        if (video_timeline->video_file_info(path, local_file)) {
                XMLNode* node = new XMLNode(X_("Videotimeline"));
-               node->add_property (X_("Filename"), path);
-               node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
-               node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
+               node->set_property (X_("Filename"), path);
+               node->set_property (X_("AutoFPS"), auto_set_session_fps);
+               node->set_property (X_("LocalFile"), local_file);
                if (orig_local_file) {
-                       node->add_property (X_("OriginalVideoFile"), orig_path);
+                       node->set_property (X_("OriginalVideoFile"), orig_path);
                } else {
                        node->remove_property (X_("OriginalVideoFile"));
                }
@@ -5165,9 +5111,9 @@ ARDOUR_UI::store_clock_modes ()
        for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
                XMLNode* child = new XMLNode (X_("Clock"));
 
-               child->add_property (X_("name"), (*x)->name());
-               child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
-               child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
+               child->set_property (X_("name"), (*x)->name());
+               child->set_property (X_("mode"), (*x)->mode());
+               child->set_property (X_("on"), (*x)->on());
 
                node->add_child_nocopy (*child);
        }
@@ -5360,6 +5306,52 @@ 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 ()
@@ -5394,10 +5386,12 @@ ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
        audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
        audio_midi_setup->set_position (WIN_POS_CENTER);
 
-       if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
-               audio_midi_setup->try_autostart ();
-               if (ARDOUR::AudioEngine::instance()->running()) {
-                       return 0;
+       if (desired_sample_rate != 0) {
+               if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
+                       audio_midi_setup->try_autostart ();
+                       if (ARDOUR::AudioEngine::instance()->running()) {
+                               return 0;
+                       }
                }
        }
 
@@ -5566,7 +5560,7 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void*
        }
 
        window.set_title (title.get_string());
-       window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
+       window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
 
        window.set_flags (CAN_FOCUS);
        window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);