Add option to use plugin GUIs or Ardour generic ones.
[ardour.git] / gtk2_ardour / rc_option_editor.cc
index 722612d21c9ffaec7d3c6d863c384c0640119aa3..5c67005386c83ee9e686d9d572b0203a111fa899 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2001-2011 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
 #ifdef WAF_BUILD
 #include "gtk2ardour-config.h"
 #endif
@@ -19,6 +38,8 @@
 #include "ardour/control_protocol_manager.h"
 #include "control_protocol/control_protocol.h"
 
+#include "ardour_window.h"
+#include "ardour_dialog.h"
 #include "gui_thread.h"
 #include "midi_tracer.h"
 #include "rc_option_editor.h"
@@ -37,7 +58,7 @@ using namespace ARDOUR;
 class ClickOptions : public OptionEditorBox
 {
 public:
-       ClickOptions (RCConfiguration* c, ArdourDialog* p)
+       ClickOptions (RCConfiguration* c, Gtk::Window* p)
                : _rc_config (c),
                  _parent (p)
        {
@@ -61,6 +82,9 @@ public:
                t->attach (*b, 2, 3, 1, 2, FILL);
 
                _box->pack_start (*t, false, false);
+
+               _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
+               _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
        }
 
        void parameter_changed (string const & p)
@@ -98,6 +122,11 @@ private:
                _rc_config->set_click_sound (path);
        }
 
+       void click_changed ()
+       {
+               click_chosen (_click_path_entry.get_text ());
+       }
+       
        void click_emphasis_browse_clicked ()
        {
                SoundFileChooser sfdb (*_parent, _("Choose Click Emphasis"));
@@ -116,8 +145,13 @@ private:
                _rc_config->set_click_emphasis_sound (path);
        }
 
+       void click_emphasis_changed ()
+       {
+               click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
+       }
+
        RCConfiguration* _rc_config;
-       ArdourDialog* _parent;
+       Gtk::Window* _parent;
        Entry _click_path_entry;
        Entry _click_emphasis_path_entry;
 };
@@ -227,7 +261,7 @@ static const struct {
        /* Command = Meta
           Option/Alt = Mod1
        */
-       { "Shift", GDK_SHIFT_MASK },
+       { "Key|Shift", GDK_SHIFT_MASK },
        { "Command", GDK_META_MASK },
        { "Control", GDK_CONTROL_MASK },
        { "Option", GDK_MOD1_MASK },
@@ -237,7 +271,7 @@ static const struct {
        { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
 
 #else
-       { "Shift", GDK_SHIFT_MASK },
+       { "Key|Shift", GDK_SHIFT_MASK },
        { "Control", GDK_CONTROL_MASK },
        { "Alt (Mod1)", GDK_MOD1_MASK },
        { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
@@ -263,14 +297,12 @@ public:
                  _edit_button_spin (_edit_button_adjustment),
                  _insert_note_button_adjustment (3, 1, 5),
                  _insert_note_button_spin (_insert_note_button_adjustment)
-
-
        {
                /* internationalize and prepare for use with combos */
 
                vector<string> dumb;
                for (int i = 0; modifiers[i].name; ++i) {
-                       dumb.push_back (_(modifiers[i].name));
+                       dumb.push_back (S_(modifiers[i].name));
                }
 
                set_popdown_strings (_edit_modifier_combo, dumb);
@@ -278,7 +310,7 @@ public:
 
                for (int x = 0; modifiers[x].name; ++x) {
                        if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
-                               _edit_modifier_combo.set_active_text (_(modifiers[x].name));
+                               _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
                                break;
                        }
                }
@@ -308,7 +340,7 @@ public:
 
                for (int x = 0; modifiers[x].name; ++x) {
                        if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
-                               _delete_modifier_combo.set_active_text (_(modifiers[x].name));
+                               _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
                                break;
                        }
                }
@@ -330,17 +362,17 @@ public:
                _delete_button_adjustment.set_value (Keyboard::delete_button());
                _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
 
-               
+
                set_popdown_strings (_insert_note_modifier_combo, dumb);
                _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
 
                for (int x = 0; modifiers[x].name; ++x) {
                        if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
-                               _insert_note_modifier_combo.set_active_text (_(modifiers[x].name));
+                               _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
                                break;
                        }
                }
-               
+
                l = manage (new Label (_("Insert note using:")));
                l->set_name ("OptionsLabel");
                l->set_alignment (0, 0.5);
@@ -357,14 +389,14 @@ public:
                _insert_note_button_spin.set_name ("OptionsEntry");
                _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
                _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
-               
-               
+
+
                set_popdown_strings (_snap_modifier_combo, dumb);
                _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
 
                for (int x = 0; modifiers[x].name; ++x) {
                        if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
-                               _snap_modifier_combo.set_active_text (_(modifiers[x].name));
+                               _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
                                break;
                        }
                }
@@ -553,7 +585,7 @@ private:
 class BufferingOptions : public OptionEditorBox
 {
 public:
-       BufferingOptions (RCConfiguration* c) 
+       BufferingOptions (RCConfiguration* c)
                 : _rc_config (c)
                , _playback_adjustment (5, 1, 60, 1, 4)
                 , _capture_adjustment (5, 1, 60, 1, 4)
@@ -572,7 +604,7 @@ public:
                h->pack_start (_playback_slider, true, true);
 
                _box->pack_start (*h, false, false);
-                
+
                _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
 
                l = manage (new Label (_("Recording (seconds of buffering):")));
@@ -585,7 +617,7 @@ public:
                h->pack_start (_capture_slider, true, true);
 
                _box->pack_start (*h, false, false);
-                
+
                _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
                _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
        }
@@ -627,7 +659,7 @@ private:
 class ControlSurfacesOptions : public OptionEditorBox
 {
 public:
-       ControlSurfacesOptions (ArdourDialog& parent)
+       ControlSurfacesOptions (Gtk::Window& parent)
                : _parent (parent)
        {
                _store = ListStore::create (_model);
@@ -645,7 +677,7 @@ public:
 
                _box->pack_start (*label, false, false);
                label->show ();
-               
+
                _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::model_changed));
                _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
        }
@@ -711,21 +743,21 @@ private:
                std::string name;
                ControlProtocolInfo* cpi;
                TreeModel::Row row;
-               
+
                row = *(_view.get_selection()->get_selected());
 
                Window* win = row[_model.editor];
                if (win && !win->is_visible()) {
-                       win->present (); 
+                       win->present ();
                } else {
                        cpi = row[_model.protocol_info];
-                       
+
                        if (cpi && cpi->protocol && cpi->protocol->has_editor ()) {
                                Box* box = (Box*) cpi->protocol->get_gui ();
                                if (box) {
                                        string title = row[_model.name];
-                                       ArdourDialog* win = new ArdourDialog (_parent, title);
-                                       win->get_vbox()->pack_start (*box, false, false);
+                                       ArdourWindow* win = new ArdourWindow (_parent, title);
+                                       win->add (*box);
                                        box->show ();
                                        win->present ();
                                        row[_model.editor] = win;
@@ -760,10 +792,69 @@ private:
         Gtk::Window& _parent;
 };
 
+/** A class which allows control of visibility of some editor components usign
+ *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
+ *  which has the correct members, but with null widget pointers.  This
+ *  class allows the user to set visibility of the members, the details
+ *  of which are stored in a configuration variable which can be watched
+ *  by parts of the editor that actually contain the widgets whose visibility
+ *  is being controlled.
+ */
+
+class VisibilityOption : public Option
+{
+public:
+       /** @param name User-visible name for this group.
+        *  @param g `Dummy' VisibilityGroup (as described above).
+        *  @param get Method to get the value of the appropriate configuration variable.
+        *  @param set Method to set the value of the appropriate configuration variable.
+        */
+       VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
+               : Option (g->get_state_name(), name)
+               , _heading (name)
+               , _visibility_group (g)
+               , _get (get)
+               , _set (set)
+       {
+               /* Watch for changes made by the user to our members */
+               _visibility_group->VisibilityChanged.connect_same_thread (
+                       _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
+                       );
+       }
+
+       void set_state_from_config ()
+       {
+               /* Set our state from the current configuration */
+               _visibility_group->set_state (_get ());
+       }
+
+       void add_to_page (OptionEditorPage* p)
+       {
+               _heading.add_to_page (p);
+               add_widget_to_page (p, _visibility_group->list_view ());
+       }
+
+private:
+       void changed ()
+       {
+               /* The user has changed something, so reflect this change
+                  in the RCConfiguration.
+               */
+               _set (_visibility_group->get_state_value ());
+       }
+       
+       OptionEditorHeading _heading;
+       VisibilityGroup* _visibility_group;
+       sigc::slot<std::string> _get;
+       sigc::slot<bool, std::string> _set;
+       PBD::ScopedConnection _visibility_group_connection;
+};
+
 
 RCOptionEditor::RCOptionEditor ()
        : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
         , _rc_config (Config)
+       , _mixer_strip_visibility ("mixer-strip-visibility")
 {
        /* MISC */
 
@@ -771,68 +862,28 @@ RCOptionEditor::RCOptionEditor ()
 
         if (hwcpus > 1) {
                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
-                
+
                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
                         "processor-usage",
                         _("Signal processing uses"),
                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
                         );
-                
+
                 procs->add (-1, _("all but one processor"));
                 procs->add (0, _("all available processors"));
-                
+
                 for (uint32_t i = 1; i <= hwcpus; ++i) {
                         procs->add (i, string_compose (_("%1 processors"), i));
                 }
-                
+
                 add_option (_("Misc"), procs);
         }
 
-       add_option (_("Misc"), new OptionEditorHeading (_("Metering")));
-
-       ComboOption<float>* mht = new ComboOption<float> (
-               "meter-hold",
-               _("Meter hold time"),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
-               );
-
-       mht->add (MeterHoldOff, _("off"));
-       mht->add (MeterHoldShort, _("short"));
-       mht->add (MeterHoldMedium, _("medium"));
-       mht->add (MeterHoldLong, _("long"));
-
-       add_option (_("Misc"), mht);
-
-       ComboOption<float>* mfo = new ComboOption<float> (
-               "meter-falloff",
-               _("Meter fall-off"),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
-               );
-
-       mfo->add (METER_FALLOFF_OFF, _("off"));
-       mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
-       mfo->add (METER_FALLOFF_SLOW, _("slow"));
-       mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
-       mfo->add (METER_FALLOFF_FAST, _("fast"));
-       mfo->add (METER_FALLOFF_FASTER, _("faster"));
-       mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
-
-       add_option (_("Misc"), mfo);
-
-       add_option (_("Misc"), new OptionEditorHeading (_("Undo")));
+       add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
 
        add_option (_("Misc"), new UndoOptions (_rc_config));
 
-       add_option (_("Misc"), new OptionEditorHeading (_("Misc")));
-
-#ifndef GTKOSX
-       /* font scaling does nothing with GDK/Quartz */
-       add_option (_("Misc"), new FontScalingOptions (_rc_config));
-#endif
-
        add_option (_("Misc"),
             new BoolOption (
                     "verify-remove-last-capture",
@@ -849,13 +900,7 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
                     ));
 
-       add_option (_("Misc"),
-            new BoolOption (
-                    "sync-all-route-ordering",
-                    _("Syncronise editor and mixer track order"),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
-                    ));
+       add_option (_("Misc"), new OptionEditorHeading (_("Misc")));
 
        add_option (_("Misc"),
             new BoolOption (
@@ -865,24 +910,15 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
                     ));
 
-       add_option (_("Misc"),
-            new BoolOption (
-                    "default-narrow_ms",
-                    _("Use narrow mixer strips"),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
-                    ));
-
-       add_option (_("Misc"),
-            new BoolOption (
-                    "name-new-markers",
-                    _("Name new markers"),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
-                    ));
+       add_option (_("Misc"), new DirectoryOption (
+                           X_("default-session-parent-dir"),
+                           _("Default folder for new sessions:"),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
+                           ));
 
        add_option (_("Misc"), new OptionEditorHeading (_("Click")));
-       
+
        add_option (_("Misc"), new ClickOptions (_rc_config, this));
 
        /* TRANSPORT */
@@ -1057,6 +1093,38 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
                            ));
 
+       add_option (_("Editor"),
+                   new BoolOption (
+                           "update-editor-during-summary-drag",
+                           _("Update editor window during drags of the summary"),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
+                           ));
+
+       add_option (_("Editor"),
+            new BoolOption (
+                    "sync-all-route-ordering",
+                    _("Synchronise editor and mixer track order"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
+                    ));
+
+       add_option (_("Editor"),
+            new BoolOption (
+                    "link-editor-and-mixer-selection",
+                    _("Synchronise editor and mixer selection"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
+                    ));
+
+       add_option (_("Editor"),
+            new BoolOption (
+                    "name-new-markers",
+                    _("Name new markers"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
+                    ));
+
        /* AUDIO */
 
        add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
@@ -1090,30 +1158,6 @@ RCOptionEditor::RCOptionEditor ()
        mm->add (ExternalMonitoring, _("audio hardware"));
 
        add_option (_("Audio"), mm);
-       
-       ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
-               "pfl-position",
-               _("PFL signals come from"),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
-               );
-
-       pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
-       pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
-
-       add_option (_("Audio"), pp);
-
-       ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
-               "afl-position",
-               _("AFL signals come from"),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
-               sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
-               );
-
-       pa->add (AFLFromBeforeProcessors, _("post-fader but before post-fader processors"));
-       pa->add (AFLFromAfterProcessors, _("after post-fader processors"));
-
-       add_option (_("Audio"), pa);
 
        add_option (_("Audio"),
             new BoolOption (
@@ -1188,7 +1232,7 @@ RCOptionEditor::RCOptionEditor ()
        }
 
        if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
-               dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZerO"));
+               dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
        }
 
        add_option (_("Audio"), dm);
@@ -1240,7 +1284,7 @@ RCOptionEditor::RCOptionEditor ()
        add_option (_("Solo / mute"),
             new FaderOption (
                     "solo-mute-gain",
-                    _("Solo mute cut (dB)"),
+                    _("Solo-in-place mute cut (dB)"),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
                     ));
@@ -1261,11 +1305,35 @@ RCOptionEditor::RCOptionEditor ()
                sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
                );
 
-       _listen_position->add (AfterFaderListen, _("after-fader listen"));
-       _listen_position->add (PreFaderListen, _("pre-fader listen"));
+       _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
+       _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
 
        add_option (_("Solo / mute"), _listen_position);
 
+       ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
+               "pfl-position",
+               _("PFL signals come from"),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
+               );
+
+       pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
+       pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
+
+       add_option (_("Solo / mute"), pp);
+
+       ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
+               "afl-position",
+               _("AFL signals come from"),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
+               );
+
+       pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
+       pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
+
+       add_option (_("Solo / mute"), pa);
+
        parameter_changed ("use-monitor-bus");
 
        add_option (_("Solo / mute"),
@@ -1293,7 +1361,7 @@ RCOptionEditor::RCOptionEditor ()
                     ));
 
        add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
-       
+
        add_option (_("Solo / mute"),
             new BoolOption (
                     "mute-affects-pre-fader",
@@ -1309,7 +1377,7 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
                     ));
-       
+
        add_option (_("Solo / mute"),
             new BoolOption (
                     "mute-affects-control-outs",
@@ -1317,7 +1385,7 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
                     ));
-       
+
        add_option (_("Solo / mute"),
             new BoolOption (
                     "mute-affects-main-outs",
@@ -1326,7 +1394,7 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
                     ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new BoolOption (
                            "send-midi-clock",
                            _("Send MIDI Clock"),
@@ -1334,7 +1402,7 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new BoolOption (
                            "send-mtc",
                            _("Send MIDI Time Code"),
@@ -1342,7 +1410,7 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new SpinOption<int> (
                            "mtc-qf-speed-tolerance",
                            _("Percentage either side of normal transport speed to transmit MTC"),
@@ -1351,7 +1419,7 @@ RCOptionEditor::RCOptionEditor ()
                            0, 20, 1, 5
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new BoolOption (
                            "mmc-control",
                            _("Obey MIDI Machine Control commands"),
@@ -1359,7 +1427,7 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new BoolOption (
                            "send-mmc",
                            _("Send MIDI Machine Control commands"),
@@ -1367,7 +1435,7 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
                    new BoolOption (
                            "midi-feedback",
                            _("Send MIDI control feedback"),
@@ -1375,7 +1443,7 @@ RCOptionEditor::RCOptionEditor ()
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
                            ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
             new SpinOption<uint8_t> (
                     "mmc-receive-device-id",
                     _("Inbound MMC device ID"),
@@ -1384,7 +1452,7 @@ RCOptionEditor::RCOptionEditor ()
                     0, 128, 1, 10
                     ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
             new SpinOption<uint8_t> (
                     "mmc-send-device-id",
                     _("Outbound MMC device ID"),
@@ -1393,7 +1461,7 @@ RCOptionEditor::RCOptionEditor ()
                     0, 128, 1, 10
                     ));
 
-       add_option (_("MIDI control"),
+       add_option (_("MIDI"),
             new SpinOption<int32_t> (
                     "initial-program-change",
                     _("Initial program change"),
@@ -1402,9 +1470,39 @@ RCOptionEditor::RCOptionEditor ()
                     -1, 65536, 1, 10
                     ));
 
-       /* CONTROL SURFACES */
+       add_option (_("MIDI"),
+                   new BoolOption (
+                           "diplay-first-midi-bank-as-zero",
+                           _("Display first MIDI bank/program as 0"),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
+                           ));
+
+       add_option (_("MIDI"),
+            new BoolOption (
+                    "never-display-periodic-midi",
+                    _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
+                    ));
+
+       add_option (_("MIDI"),
+            new BoolOption (
+                    "sound-midi-notes",
+                    _("Sound MIDI notes as they are selected"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
+                    ));
+
+       /* USER INTERACTION */
+
+       add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
+
+       add_option (_("User interaction"), new KeyboardOptions);
 
-       add_option (_("Control surfaces"), new ControlSurfacesOptions (*this));
+       add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
+
+       add_option (_("User interaction"), new ControlSurfacesOptions (*this));
 
        ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
                "remote-model",
@@ -1417,18 +1515,97 @@ RCOptionEditor::RCOptionEditor ()
        rm->add (MixerOrdered, _("follows order of mixer"));
        rm->add (EditorOrdered, _("follows order of editor"));
 
-       add_option (_("Control surfaces"), rm);
+       add_option (_("User interaction"), rm);
+
+       /* INTERFACE */
+
+       add_option (S_("Visual|Interface"),
+            new BoolOption (
+                    "widget-prelight",
+                    _("Graphically indicate mouse pointer hovering over various widgets"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
+                    ));
+
+#ifndef GTKOSX
+       /* font scaling does nothing with GDK/Quartz */
+       add_option (S_("Visual|Interface"), new FontScalingOptions (_rc_config));
+#endif
+       add_option (S_("Visual|Interface"),
+                   new BoolOption (
+                           "use-own-plugin-gui",
+                           _("Use plugins' own interface instead of Ardour's basic one"),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
+                           sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
+                           ));
+
+       /* The names of these controls must be the same as those given in MixerStrip
+          for the actual widgets being controlled.
+       */
+       _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
+       _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
+       _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
+       _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
+       _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
+       _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
+       
+       add_option (
+               S_("Visual|Interface"),
+               new VisibilityOption (
+                       _("Mixer Strip"),
+                       &_mixer_strip_visibility,
+                       sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
+                       sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
+                       )
+               );
 
-       /* KEYBOARD */
+       add_option (S_("Visual|Interface"),
+            new BoolOption (
+                    "default-narrow_ms",
+                    _("Use narrow mixer strips by default"),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
+                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
+                    ));
+
+       add_option (S_("Visual|Interface"), new OptionEditorHeading (_("Metering")));
 
-       add_option (_("Keyboard"), new KeyboardOptions);
+       ComboOption<float>* mht = new ComboOption<float> (
+               "meter-hold",
+               _("Meter hold time"),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
+               );
+
+       mht->add (MeterHoldOff, _("off"));
+       mht->add (MeterHoldShort, _("short"));
+       mht->add (MeterHoldMedium, _("medium"));
+       mht->add (MeterHoldLong, _("long"));
+
+       add_option (S_("Visual|Interface"), mht);
+
+       ComboOption<float>* mfo = new ComboOption<float> (
+               "meter-falloff",
+               _("Meter fall-off"),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
+               sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
+               );
+
+       mfo->add (METER_FALLOFF_OFF, _("off"));
+       mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
+       mfo->add (METER_FALLOFF_SLOW, _("slow"));
+       mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
+       mfo->add (METER_FALLOFF_FAST, _("fast"));
+       mfo->add (METER_FALLOFF_FASTER, _("faster"));
+       mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
+
+       add_option (S_("Visual|Interface"), mfo);
 }
 
 void
 RCOptionEditor::parameter_changed (string const & p)
 {
        OptionEditor::parameter_changed (p);
-       
+
        if (p == "use-monitor-bus") {
                bool const s = Config->get_use_monitor_bus ();
                if (!s) {