allow the use of static_cast for MGR ghost events (speeds things up a bit).
[ardour.git] / gtk2_ardour / rc_option_editor.cc
index 1c1783bd373f7b62aaedd3894d58014c78847cbf..30b55259bd89c8b585a481e47625a3d64e740c6a 100644 (file)
@@ -77,7 +77,7 @@ using namespace PBD;
 using namespace ARDOUR;
 using namespace ARDOUR_UI_UTILS;
 
-class ClickOptions : public OptionEditorBox
+class ClickOptions : public OptionEditorPageBox, public OptionEditorPage
 {
 public:
        ClickOptions (RCConfiguration* c)
@@ -85,36 +85,45 @@ public:
                , _click_browse_button (_("Browse..."))
                , _click_emphasis_browse_button (_("Browse..."))
        {
-               Table* t = manage (new Table (4, 3));
-               t->set_spacings (4);
+               Table* t = &table;
 
                Label* l = manage (left_aligned_label (_("Emphasis on first beat:")));
-               t->attach (*l, 0, 1, 1, 2, FILL);
-               t->attach (_use_emphasis_on_click_check_button, 1, 2, 1, 2, FILL);
+               _use_emphasis_on_click_check_button.add (*l);
+               t->attach (_use_emphasis_on_click_check_button, 1, 3, 0, 1, FILL);
                _use_emphasis_on_click_check_button.signal_toggled().connect (
                    sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
 
                l = manage (left_aligned_label (_("Use default Click:")));
-               t->attach (*l, 0, 1, 0, 1, FILL);
-               t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
+               _use_default_click_check_button.add (*l);
+               t->attach (_use_default_click_check_button, 1, 3, 1, 2, FILL);
                _use_default_click_check_button.signal_toggled().connect (
                    sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
 
                l = manage (left_aligned_label (_("Click audio file:")));
-               t->attach (*l, 0, 1, 2, 3, FILL);
-               t->attach (_click_path_entry, 1, 2, 2, 3, FILL);
+               t->attach (*l, 1, 2, 2, 3, FILL);
+               t->attach (_click_path_entry, 2, 3, 2, 3, FILL);
                _click_browse_button.signal_clicked ().connect (
                    sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
-               t->attach (_click_browse_button, 2, 3, 2, 3, FILL);
+               t->attach (_click_browse_button, 3, 4, 2, 3, FILL);
 
                l = manage (left_aligned_label (_("Click emphasis audio file:")));
-               t->attach (*l, 0, 1, 3, 4, FILL);
-               t->attach (_click_emphasis_path_entry, 1, 2, 3, 4, FILL);
+               t->attach (*l, 1, 2, 3, 4, FILL);
+               t->attach (_click_emphasis_path_entry, 2, 3, 3, 4, FILL);
                _click_emphasis_browse_button.signal_clicked ().connect (
                    sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
-               t->attach (_click_emphasis_browse_button, 2, 3, 3, 4, FILL);
+               t->attach (_click_emphasis_browse_button, 3, 4, 3, 4, FILL);
+
+               FaderOption* fo = new FaderOption (
+                               "click-gain",
+                               _("Click gain level"),
+                               sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
+                               sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
+                               );
 
-               _box->pack_start (*t, true, false);
+               fo->add_to_page (this);
+               fo->set_state_from_config ();
+
+               _box->pack_start (table, true, true);
 
                _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));
@@ -324,8 +333,8 @@ private:
 
 
 static const struct {
-    const char *name;
-    guint modifier;
+       const char *name;
+       guint modifier;
 } modifiers[] = {
 
        { "Unmodified", 0 },
@@ -1205,13 +1214,13 @@ private:
 
 class BufferingOptions : public OptionEditorBox
 {
-public:
-       BufferingOptions (RCConfiguration* c)
-                : _rc_config (c)
-               , _playback_adjustment (5, 1, 60, 1, 4)
-                , _capture_adjustment (5, 1, 60, 1, 4)
-                , _playback_slider (_playback_adjustment)
-               , _capture_slider (_capture_adjustment)
+       public:
+               BufferingOptions (RCConfiguration* c)
+                       : _rc_config (c)
+                       , _playback_adjustment (5, 1, 60, 1, 4)
+                       , _capture_adjustment (5, 1, 60, 1, 4)
+                       , _playback_slider (_playback_adjustment)
+                       , _capture_slider (_capture_adjustment)
        {
                vector<string> presets;
 
@@ -1264,467 +1273,460 @@ public:
                _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
        }
 
-       void parameter_changed (string const & p)
-       {
-               if (p == "buffering-preset") {
-                       switch (_rc_config->get_buffering_preset()) {
-                       case Small:
-                               _playback_slider.set_sensitive (false);
-                               _capture_slider.set_sensitive (false);
-                               _buffering_presets_combo.set_active (0);
-                               break;
-                       case Medium:
-                               _playback_slider.set_sensitive (false);
-                               _capture_slider.set_sensitive (false);
-                               _buffering_presets_combo.set_active (1);
-                               break;
-                       case Large:
-                               _playback_slider.set_sensitive (false);
-                               _capture_slider.set_sensitive (false);
-                               _buffering_presets_combo.set_active (2);
-                               break;
-                       case Custom:
-                               _playback_slider.set_sensitive (true);
-                               _capture_slider.set_sensitive (true);
-                               _buffering_presets_combo.set_active (3);
-                               break;
+               void parameter_changed (string const & p)
+               {
+                       if (p == "buffering-preset") {
+                               switch (_rc_config->get_buffering_preset()) {
+                                       case Small:
+                                               _playback_slider.set_sensitive (false);
+                                               _capture_slider.set_sensitive (false);
+                                               _buffering_presets_combo.set_active (0);
+                                               break;
+                                       case Medium:
+                                               _playback_slider.set_sensitive (false);
+                                               _capture_slider.set_sensitive (false);
+                                               _buffering_presets_combo.set_active (1);
+                                               break;
+                                       case Large:
+                                               _playback_slider.set_sensitive (false);
+                                               _capture_slider.set_sensitive (false);
+                                               _buffering_presets_combo.set_active (2);
+                                               break;
+                                       case Custom:
+                                               _playback_slider.set_sensitive (true);
+                                               _capture_slider.set_sensitive (true);
+                                               _buffering_presets_combo.set_active (3);
+                                               break;
+                               }
                        }
-               }
 
-               if (p == "playback-buffer-seconds") {
-                       _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
-               } else if (p == "capture-buffer-seconds") {
-                       _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
-                }
-       }
+                       if (p == "playback-buffer-seconds") {
+                               _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
+                       } else if (p == "capture-buffer-seconds") {
+                               _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
+                       }
+               }
 
-       void set_state_from_config ()
-       {
-               parameter_changed ("buffering-preset");
-               parameter_changed ("playback-buffer-seconds");
-               parameter_changed ("capture-buffer-seconds");
-       }
+               void set_state_from_config ()
+               {
+                       parameter_changed ("buffering-preset");
+                       parameter_changed ("playback-buffer-seconds");
+                       parameter_changed ("capture-buffer-seconds");
+               }
 
-private:
+       private:
 
-       void preset_changed ()
-       {
-               int index = _buffering_presets_combo.get_active_row_number ();
-               if (index < 0) {
-                       return;
-               }
-               switch (index) {
-               case 0:
-                       _rc_config->set_buffering_preset (Small);
-                       break;
-               case 1:
-                       _rc_config->set_buffering_preset (Medium);
-                       break;
-               case 2:
-                       _rc_config->set_buffering_preset (Large);
-                       break;
-               case 3:
-                       _rc_config->set_buffering_preset (Custom);
-                       break;
-               default:
-                       error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
-                       break;
+               void preset_changed ()
+               {
+                       int index = _buffering_presets_combo.get_active_row_number ();
+                       if (index < 0) {
+                               return;
+                       }
+                       switch (index) {
+                               case 0:
+                                       _rc_config->set_buffering_preset (Small);
+                                       break;
+                               case 1:
+                                       _rc_config->set_buffering_preset (Medium);
+                                       break;
+                               case 2:
+                                       _rc_config->set_buffering_preset (Large);
+                                       break;
+                               case 3:
+                                       _rc_config->set_buffering_preset (Custom);
+                                       break;
+                               default:
+                                       error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
+                                       break;
+                       }
                }
-       }
 
-       void playback_changed ()
-       {
-               _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
-       }
+               void playback_changed ()
+               {
+                       _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
+               }
 
-       void capture_changed ()
-       {
-               _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
-       }
+               void capture_changed ()
+               {
+                       _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
+               }
 
-       RCConfiguration* _rc_config;
-       Adjustment _playback_adjustment;
-       Adjustment _capture_adjustment;
-       HScale _playback_slider;
-       HScale _capture_slider;
-       ComboBoxText _buffering_presets_combo;
+               RCConfiguration* _rc_config;
+               Adjustment _playback_adjustment;
+               Adjustment _capture_adjustment;
+               HScale _playback_slider;
+               HScale _capture_slider;
+               ComboBoxText _buffering_presets_combo;
 };
 
-class ControlSurfacesOptions : public OptionEditorBox
+class ControlSurfacesOptions : public OptionEditorPageBox
 {
-public:
-       ControlSurfacesOptions ()
-               : _ignore_view_change (0)
-       {
-               _store = ListStore::create (_model);
-               _view.set_model (_store);
-               _view.append_column (_("Control Surface Protocol"), _model.name);
-               _view.get_column(0)->set_resizable (true);
-               _view.get_column(0)->set_expand (true);
-               _view.append_column_editable (_("Enabled"), _model.enabled);
-               _view.append_column_editable (_("Feedback"), _model.feedback);
-
-               _box->pack_start (_view, false, false);
-
-               Gtk::HBox* edit_box = manage (new Gtk::HBox);
-               edit_box->set_spacing(3);
-               _box->pack_start (*edit_box, false, false);
-               edit_box->show ();
-
-               Label* label = manage (new Label);
-               label->set_text (_("Click to edit the settings for selected protocol ( it must be ENABLED first ):"));
-               edit_box->pack_start (*label, false, false);
-               label->show ();
-
-               edit_button = manage (new Button(_("Show Protocol Settings")));
-               edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
-               edit_box->pack_start (*edit_button, true, true);
-               edit_button->set_sensitive (false);
-               edit_button->show ();
-
-               ControlProtocolManager& m = ControlProtocolManager::instance ();
-               m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
-                                               boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
-
-               _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
-               _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
-               _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
-       }
-
-       void parameter_changed (std::string const &)
-       {
+       public:
+               ControlSurfacesOptions ()
+                       : _ignore_view_change (0)
+               {
+                       _store = ListStore::create (_model);
+                       _view.set_model (_store);
+                       _view.append_column (_("Control Surface Protocol"), _model.name);
+                       _view.get_column(0)->set_resizable (true);
+                       _view.get_column(0)->set_expand (true);
+                       _view.append_column_editable (_("Enable"), _model.enabled);
+
+                       Label* l = manage (new Label (string_compose ("<b>%1</b>", _("Control Surfaces"))));
+                       l->set_alignment (0, 0.5);
+                       l->set_use_markup (true);
+                       _box->pack_start (*l, false, false);
+                       _box->pack_start (_view, false, false);
+
+                       Gtk::HBox* edit_box = manage (new Gtk::HBox);
+                       edit_box->set_spacing(3);
+                       _box->pack_start (*edit_box, false, false);
+                       edit_box->show ();
+
+                       Label* label = manage (new Label);
+                       label->set_text (_("Edit the settings for selected protocol (it must be ENABLED first):"));
+                       edit_box->pack_start (*label, false, false);
+                       label->show ();
+
+                       edit_button = manage (new Button(_("Show Protocol Settings")));
+                       edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
+                       edit_box->pack_start (*edit_button, true, true);
+                       edit_button->set_sensitive (false);
+                       edit_button->show ();
 
-       }
+                       ControlProtocolManager& m = ControlProtocolManager::instance ();
+                       m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
+                                       boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
 
-       void set_state_from_config ()
-       {
-               _store->clear ();
+                       _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
+                       _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
+                       _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
+               }
 
-               ControlProtocolManager& m = ControlProtocolManager::instance ();
-               for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
+               void parameter_changed (std::string const &)
+               {
 
-                       if (!(*i)->mandatory) {
-                               TreeModel::Row r = *_store->append ();
-                               r[_model.name] = (*i)->name;
-                               r[_model.enabled] = ((*i)->protocol || (*i)->requested);
-                               r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
-                               r[_model.protocol_info] = *i;
-                       }
                }
-       }
-
-private:
 
-        void protocol_status_changed (ControlProtocolInfo* cpi) {
-               /* find the row */
-               TreeModel::Children rows = _store->children();
+               void set_state_from_config ()
+               {
+                       _store->clear ();
 
-               for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
-                       string n = ((*x)[_model.name]);
+                       ControlProtocolManager& m = ControlProtocolManager::instance ();
+                       for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
 
-                       if ((*x)[_model.protocol_info] == cpi) {
-                               _ignore_view_change++;
-                               (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
-                               _ignore_view_change--;
-                               break;
+                               if (!(*i)->mandatory) {
+                                       TreeModel::Row r = *_store->append ();
+                                       r[_model.name] = (*i)->name;
+                                       r[_model.enabled] = ((*i)->protocol || (*i)->requested);
+                                       r[_model.protocol_info] = *i;
+                               }
                        }
                }
-       }
 
-       void selection_changed ()
-       {
-               //enable the Edit button when a row is selected for editing
-               TreeModel::Row row = *(_view.get_selection()->get_selected());
-               if (row && row[_model.enabled])
-                       edit_button->set_sensitive (true);
-               else
-                       edit_button->set_sensitive (false);
-       }
+       private:
 
-       void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
-       {
-               TreeModel::Row r = *i;
+               void protocol_status_changed (ControlProtocolInfo* cpi) {
+                       /* find the row */
+                       TreeModel::Children rows = _store->children();
 
-               if (_ignore_view_change) {
-                       return;
-               }
+                       for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
+                               string n = ((*x)[_model.name]);
 
-               ControlProtocolInfo* cpi = r[_model.protocol_info];
-               if (!cpi) {
-                       return;
+                               if ((*x)[_model.protocol_info] == cpi) {
+                                       _ignore_view_change++;
+                                       (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
+                                       _ignore_view_change--;
+                                       break;
+                               }
+                       }
                }
 
-               bool const was_enabled = (cpi->protocol != 0);
-               bool const is_enabled = r[_model.enabled];
+               void selection_changed ()
+               {
+                       //enable the Edit button when a row is selected for editing
+                       TreeModel::Row row = *(_view.get_selection()->get_selected());
+                       if (row && row[_model.enabled])
+                               edit_button->set_sensitive (true);
+                       else
+                               edit_button->set_sensitive (false);
+               }
 
+               void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
+               {
+                       TreeModel::Row r = *i;
 
-               if (was_enabled != is_enabled) {
+                       if (_ignore_view_change) {
+                               return;
+                       }
 
-                       if (!was_enabled) {
-                               ControlProtocolManager::instance().activate (*cpi);
-                       } else {
-                               ControlProtocolManager::instance().deactivate (*cpi);
+                       ControlProtocolInfo* cpi = r[_model.protocol_info];
+                       if (!cpi) {
+                               return;
                        }
-               }
 
-               bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
-               bool const is_feedback = r[_model.feedback];
+                       bool const was_enabled = (cpi->protocol != 0);
+                       bool const is_enabled = r[_model.enabled];
 
-               if (was_feedback != is_feedback && cpi->protocol) {
-                       cpi->protocol->set_feedback (is_feedback);
-               }
-       }
 
-       void edit_btn_clicked ()
-       {
-               std::string name;
-               ControlProtocolInfo* cpi;
-               TreeModel::Row row;
-
-               row = *(_view.get_selection()->get_selected());
-               if (!row[_model.enabled]) {
-                       return;
-               }
-               cpi = row[_model.protocol_info];
-               if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
-                       return;
-               }
-               Box* box = (Box*) cpi->protocol->get_gui ();
-               if (!box) {
-                       return;
-               }
-               if (box->get_parent()) {
-                       static_cast<ArdourWindow*>(box->get_parent())->present();
-                       return;
-               }
-               WindowTitle title (Glib::get_application_name());
-               title += row[_model.name];
-               title += _("Configuration");
-               /* once created, the window is managed by the surface itself (as ->get_parent())
-                * Surface's tear_down_gui() is called on session close, when de-activating
-                * or re-initializing a surface.
-                * tear_down_gui() hides an deletes the Window if it exists.
-                */
-               ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
-               win->set_title ("Control Protocol Options");
-               win->add (*box);
-               box->show ();
-               win->present ();
-       }
-
-       void edit_clicked (GdkEventButton* ev)
-       {
-               if (ev->type != GDK_2BUTTON_PRESS) {
-                       return;
-               }
+                       if (was_enabled != is_enabled) {
 
-               edit_btn_clicked();
-       }
+                               if (!was_enabled) {
+                                       ControlProtocolManager::instance().activate (*cpi);
+                               } else {
+                                       ControlProtocolManager::instance().deactivate (*cpi);
+                               }
+                       }
 
-        class ControlSurfacesModelColumns : public TreeModelColumnRecord
-       {
-       public:
+                       selection_changed ();
+               }
 
-               ControlSurfacesModelColumns ()
+               void edit_btn_clicked ()
                {
-                       add (name);
-                       add (enabled);
-                       add (feedback);
-                       add (protocol_info);
-               }
+                       std::string name;
+                       ControlProtocolInfo* cpi;
+                       TreeModel::Row row;
 
-               TreeModelColumn<string> name;
-               TreeModelColumn<bool> enabled;
-               TreeModelColumn<bool> feedback;
-               TreeModelColumn<ControlProtocolInfo*> protocol_info;
-       };
+                       row = *(_view.get_selection()->get_selected());
+                       if (!row[_model.enabled]) {
+                               return;
+                       }
+                       cpi = row[_model.protocol_info];
+                       if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
+                               return;
+                       }
+                       Box* box = (Box*) cpi->protocol->get_gui ();
+                       if (!box) {
+                               return;
+                       }
+                       if (box->get_parent()) {
+                               static_cast<ArdourWindow*>(box->get_parent())->present();
+                               return;
+                       }
+                       WindowTitle title (Glib::get_application_name());
+                       title += row[_model.name];
+                       title += _("Configuration");
+                       /* once created, the window is managed by the surface itself (as ->get_parent())
+                        * Surface's tear_down_gui() is called on session close, when de-activating
+                        * or re-initializing a surface.
+                        * tear_down_gui() hides an deletes the Window if it exists.
+                        */
+                       ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
+                       win->set_title ("Control Protocol Options");
+                       win->add (*box);
+                       box->show ();
+                       win->present ();
+               }
+
+               void edit_clicked (GdkEventButton* ev)
+               {
+                       if (ev->type != GDK_2BUTTON_PRESS) {
+                               return;
+                       }
 
-       Glib::RefPtr<ListStore> _store;
-       ControlSurfacesModelColumns _model;
-       TreeView _view;
-        PBD::ScopedConnection protocol_status_connection;
-        uint32_t _ignore_view_change;
-       Gtk::Button* edit_button;
-};
+                       edit_btn_clicked();
+               }
 
-class VideoTimelineOptions : public OptionEditorBox
-{
-public:
-       VideoTimelineOptions (RCConfiguration* c)
-               : _rc_config (c)
-               , _show_video_export_info_button (_("Show Video Export Info before export"))
-               , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
-               , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
-               , _xjadeo_browse_button (_("Browse..."))
+               class ControlSurfacesModelColumns : public TreeModelColumnRecord
        {
-               Table* t = manage (new Table (8, 4));
-               t->set_spacings (4);
+               public:
 
-               std::stringstream s;
-               s << "<b>" << _("Video Server") << "</b>";
-               Label* l = manage (new Label (s.str()));
-               l->set_use_markup (true);
-               l->set_alignment (0, 0.5);
-               t->attach (*l, 0, 4, 0, 1, EXPAND | FILL, FILL | EXPAND, 0, 8);
+                       ControlSurfacesModelColumns ()
+                       {
+                               add (name);
+                               add (enabled);
+                               add (protocol_info);
+                       }
 
-               t->attach (_video_advanced_setup_button, 1, 4, 1, 2);
-               _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
-               Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
-                                           _("<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do not enable this option unless you know what you are doing."));
+                       TreeModelColumn<string> name;
+                       TreeModelColumn<bool> enabled;
+                       TreeModelColumn<ControlProtocolInfo*> protocol_info;
+       };
 
-               l = manage (new Label (_("Video Server URL:")));
-               l->set_alignment (0, 0.5);
-               t->attach (*l, 1, 2, 2, 3, FILL);
-               t->attach (_video_server_url_entry, 2, 4, 2, 3, FILL);
-               Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
-                                           _("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is running locally"));
+               Glib::RefPtr<ListStore> _store;
+               ControlSurfacesModelColumns _model;
+               TreeView _view;
+               PBD::ScopedConnection protocol_status_connection;
+               uint32_t _ignore_view_change;
+               Gtk::Button* edit_button;
+};
 
-               l = manage (new Label (_("Video Folder:")));
-               l->set_alignment (0, 0.5);
-               t->attach (*l, 1, 2, 3, 4, FILL);
-               t->attach (_video_server_docroot_entry, 2, 4, 3, 4);
-               Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
-                                           _("Local path to the video-server document-root. Only files below this directory will be accessible by the video-server. If the server run on a remote host, it should point to a network mounted folder of the server's docroot or be left empty if it is unvailable. It is used for the local video-monitor and file-browsing when opening/adding a video file."));
-
-               t->attach (_show_video_export_info_button, 1, 4, 4, 5);
-               _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
-               Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
-                                           _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
-
-               t->attach (_show_video_server_dialog_button, 1, 4, 5, 6);
-               _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
-               Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
-                                           _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
-
-               s.str (std::string ());
-               s << "<b>" << _("Video Monitor") << "</b>";
-               l = manage (new Label (s.str()));
-               l->set_use_markup (true);
-               l->set_alignment (0, 0.5);
-               t->attach (*l, 0, 4, 6, 7, EXPAND | FILL, FILL | EXPAND, 0, 8);
-
-               l = manage (new Label (string_compose (_("Custom Path to Video Monitor (%1) - leave empty for default:"),
+class VideoTimelineOptions : public OptionEditorPageBox, public OptionEditorPage
+{
+       public:
+               VideoTimelineOptions (RCConfiguration* c)
+                       : _rc_config (c)
+                       , _show_video_export_info_button (_("Show Video Export Info before export"))
+                       , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
+                       , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
+                       , _xjadeo_browse_button (_("Browse..."))
+               {
+                       Table* t = &table;
+
+                       Label* l = manage (new Label (string_compose ("<b>%1</b>", _("Video Server"))));
+                       l->set_use_markup (true);
+                       l->set_alignment (0, 0.5);
+                       t->attach (*l, 0, 4, 0, 1, EXPAND | FILL, FILL | EXPAND, 0, 0);
+
+                       t->attach (_show_video_export_info_button, 1, 4, 1, 2);
+                       _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
+                       Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
+                                       _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
+
+                       t->attach (_show_video_server_dialog_button, 1, 4, 2, 3);
+                       _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
+                       Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
+                                       _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
+
+                       t->attach (_video_advanced_setup_button, 1, 4, 3, 4, FILL);
+                       _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
+                       Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
+                                       _("<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do not enable this option unless you know what you are doing."));
+
+                       l = manage (new Label (_("Video Server URL:")));
+                       l->set_alignment (0, 0.5);
+                       t->attach (*l, 1, 2, 4, 5, FILL);
+                       t->attach (_video_server_url_entry, 2, 4, 4, 5, FILL);
+                       Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
+                                       _("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is running locally"));
+
+                       l = manage (new Label (_("Video Folder:")));
+                       l->set_alignment (0, 0.5);
+                       t->attach (*l, 1, 2, 5, 6, FILL);
+                       t->attach (_video_server_docroot_entry, 2, 4, 5, 6);
+                       Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
+                                       _("Local path to the video-server document-root. Only files below this directory will be accessible by the video-server. If the server run on a remote host, it should point to a network mounted folder of the server's docroot or be left empty if it is unvailable. It is used for the local video-monitor and file-browsing when opening/adding a video file."));
+
+                       l = manage (new Label (""));
+                       t->attach (*l, 0, 4, 6, 7, EXPAND | FILL);
+
+                       l = manage (new Label (string_compose ("<b>%1</b>", _("Video Monitor"))));
+                       l->set_use_markup (true);
+                       l->set_alignment (0, 0.5);
+                       t->attach (*l, 0, 4, 7, 8, EXPAND | FILL);
+
+                       l = manage (new Label (string_compose (_("Custom Path to Video Monitor (%1) - leave empty for default:"),
 #ifdef __APPLE__
-                                               "Jadeo.app"
+                                                       "Jadeo.app"
 #elif defined PLATFORM_WINDOWS
-                                               "xjadeo.exe"
+                                                       "xjadeo.exe"
 #else
-                                               "xjadeo"
+                                                       "xjadeo"
 #endif
-                                               )));
-               l->set_alignment (0, 0.5);
-               t->attach (*l, 1, 4, 7, 8, FILL);
-               t->attach (_custom_xjadeo_path, 2, 3, 8, 9);
-               Gtkmm2ext::UI::instance()->set_tip (_custom_xjadeo_path, _("Set a custom path to the Video Monitor Executable, changing this requires a restart."));
-               t->attach (_xjadeo_browse_button, 3, 4, 8, 9, FILL);
+                                                       )));
+                       l->set_alignment (0, 0.5);
+                       t->attach (*l, 1, 4, 8, 9, FILL);
+                       t->attach (_custom_xjadeo_path, 2, 3, 9, 10, EXPAND|FILL);
+                       Gtkmm2ext::UI::instance()->set_tip (_custom_xjadeo_path, _("Set a custom path to the Video Monitor Executable, changing this requires a restart."));
+                       t->attach (_xjadeo_browse_button, 3, 4, 9, 10, FILL);
 
-               _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
-               _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
-               _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
-               _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
-               _custom_xjadeo_path.signal_changed().connect (sigc::mem_fun (*this, &VideoTimelineOptions::custom_xjadeo_path_changed));
-               _xjadeo_browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &VideoTimelineOptions::xjadeo_browse_clicked));
+                       _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
+                       _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
+                       _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
+                       _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
+                       _custom_xjadeo_path.signal_changed().connect (sigc::mem_fun (*this, &VideoTimelineOptions::custom_xjadeo_path_changed));
+                       _xjadeo_browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &VideoTimelineOptions::xjadeo_browse_clicked));
 
-               // xjadeo-path is a UIConfig parameter
-               UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &VideoTimelineOptions::parameter_changed));
+                       // xjadeo-path is a UIConfig parameter
+                       UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &VideoTimelineOptions::parameter_changed));
 
-               _box->pack_start (*t,true,true);
-       }
+                       _box->pack_start (*t, true, true);
+               }
 
-       void server_url_changed ()
-       {
-               _rc_config->set_video_server_url (_video_server_url_entry.get_text());
-       }
+               void server_url_changed ()
+               {
+                       _rc_config->set_video_server_url (_video_server_url_entry.get_text());
+               }
 
-       void server_docroot_changed ()
-       {
-               _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
-       }
+               void server_docroot_changed ()
+               {
+                       _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
+               }
 
-       void show_video_export_info_toggled ()
-       {
-               bool const x = _show_video_export_info_button.get_active ();
-               _rc_config->set_show_video_export_info (x);
-       }
+               void show_video_export_info_toggled ()
+               {
+                       bool const x = _show_video_export_info_button.get_active ();
+                       _rc_config->set_show_video_export_info (x);
+               }
 
-       void show_video_server_dialog_toggled ()
-       {
-               bool const x = _show_video_server_dialog_button.get_active ();
-               _rc_config->set_show_video_server_dialog (x);
-       }
+               void show_video_server_dialog_toggled ()
+               {
+                       bool const x = _show_video_server_dialog_button.get_active ();
+                       _rc_config->set_show_video_server_dialog (x);
+               }
 
-       void video_advanced_setup_toggled ()
-       {
-               bool const x = _video_advanced_setup_button.get_active ();
-               _rc_config->set_video_advanced_setup(x);
-       }
+               void video_advanced_setup_toggled ()
+               {
+                       bool const x = _video_advanced_setup_button.get_active ();
+                       _rc_config->set_video_advanced_setup(x);
+               }
 
-       void custom_xjadeo_path_changed ()
-       {
-               UIConfiguration::instance().set_xjadeo_binary (_custom_xjadeo_path.get_text());
-       }
+               void custom_xjadeo_path_changed ()
+               {
+                       UIConfiguration::instance().set_xjadeo_binary (_custom_xjadeo_path.get_text());
+               }
 
-       void xjadeo_browse_clicked ()
-       {
-               Gtk::FileChooserDialog dialog(_("Set Video Monitor Executable"), Gtk::FILE_CHOOSER_ACTION_OPEN);
-               dialog.set_filename (UIConfiguration::instance().get_xjadeo_binary());
-               dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-               dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
-               if (dialog.run () == Gtk::RESPONSE_OK) {
-                       const std::string& filename = dialog.get_filename();
-                       if (!filename.empty() && (
+               void xjadeo_browse_clicked ()
+               {
+                       Gtk::FileChooserDialog dialog(_("Set Video Monitor Executable"), Gtk::FILE_CHOOSER_ACTION_OPEN);
+                       dialog.set_filename (UIConfiguration::instance().get_xjadeo_binary());
+                       dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+                       dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
+                       if (dialog.run () == Gtk::RESPONSE_OK) {
+                               const std::string& filename = dialog.get_filename();
+                               if (!filename.empty() && (
 #ifdef __APPLE__
-                                       Glib::file_test (filename + "/Contents/MacOS/xjadeo", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE) ||
+                                                       Glib::file_test (filename + "/Contents/MacOS/xjadeo", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE) ||
 #endif
-                                       Glib::file_test (filename, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE)
-                                       )) {
-                               UIConfiguration::instance().set_xjadeo_binary (filename);
+                                                       Glib::file_test (filename, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE)
+                                                       )) {
+                                       UIConfiguration::instance().set_xjadeo_binary (filename);
+                               }
                        }
                }
-       }
 
-       void parameter_changed (string const & p)
-       {
-               if (p == "video-server-url") {
-                       _video_server_url_entry.set_text (_rc_config->get_video_server_url());
-               } else if (p == "video-server-docroot") {
-                       _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
-               } else if (p == "show-video-export-info") {
-                       bool const x = _rc_config->get_show_video_export_info();
-                       _show_video_export_info_button.set_active (x);
-               } else if (p == "show-video-server-dialog") {
-                       bool const x = _rc_config->get_show_video_server_dialog();
-                       _show_video_server_dialog_button.set_active (x);
-               } else if (p == "video-advanced-setup") {
-                       bool const x = _rc_config->get_video_advanced_setup();
-                       _video_advanced_setup_button.set_active(x);
-                       _video_server_docroot_entry.set_sensitive(x);
-                       _video_server_url_entry.set_sensitive(x);
-               } else if (p == "xjadeo-binary") {
-                       _custom_xjadeo_path.set_text (UIConfiguration::instance().get_xjadeo_binary());
+               void parameter_changed (string const & p)
+               {
+                       if (p == "video-server-url") {
+                               _video_server_url_entry.set_text (_rc_config->get_video_server_url());
+                       } else if (p == "video-server-docroot") {
+                               _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
+                       } else if (p == "show-video-export-info") {
+                               bool const x = _rc_config->get_show_video_export_info();
+                               _show_video_export_info_button.set_active (x);
+                       } else if (p == "show-video-server-dialog") {
+                               bool const x = _rc_config->get_show_video_server_dialog();
+                               _show_video_server_dialog_button.set_active (x);
+                       } else if (p == "video-advanced-setup") {
+                               bool const x = _rc_config->get_video_advanced_setup();
+                               _video_advanced_setup_button.set_active(x);
+                               _video_server_docroot_entry.set_sensitive(x);
+                               _video_server_url_entry.set_sensitive(x);
+                       } else if (p == "xjadeo-binary") {
+                               _custom_xjadeo_path.set_text (UIConfiguration::instance().get_xjadeo_binary());
+                       }
                }
-       }
 
-       void set_state_from_config ()
-       {
-               parameter_changed ("video-server-url");
-               parameter_changed ("video-server-docroot");
-               parameter_changed ("video-monitor-setup-dialog");
-               parameter_changed ("show-video-export-info");
-               parameter_changed ("show-video-server-dialog");
-               parameter_changed ("video-advanced-setup");
-               parameter_changed ("xjadeo-binary");
-       }
+               void set_state_from_config ()
+               {
+                       parameter_changed ("video-server-url");
+                       parameter_changed ("video-server-docroot");
+                       parameter_changed ("video-monitor-setup-dialog");
+                       parameter_changed ("show-video-export-info");
+                       parameter_changed ("show-video-server-dialog");
+                       parameter_changed ("video-advanced-setup");
+                       parameter_changed ("xjadeo-binary");
+               }
 
-private:
-       RCConfiguration* _rc_config;
-       Entry _video_server_url_entry;
-       Entry _video_server_docroot_entry;
-       Entry _custom_xjadeo_path;
-       CheckButton _show_video_export_info_button;
-       CheckButton _show_video_server_dialog_button;
-       CheckButton _video_advanced_setup_button;
-       Button _xjadeo_browse_button;
+       private:
+               RCConfiguration* _rc_config;
+               Entry _video_server_url_entry;
+               Entry _video_server_docroot_entry;
+               Entry _custom_xjadeo_path;
+               CheckButton _show_video_export_info_button;
+               CheckButton _show_video_server_dialog_button;
+               CheckButton _video_advanced_setup_button;
+               Button _xjadeo_browse_button;
 };
 
 class ColumVisibilityOption : public Option
@@ -1836,7 +1838,7 @@ public:
                add_widget_to_page (p, _visibility_group->list_view ());
        }
 
-        Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
+       Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
 
 private:
        void changed ()
@@ -1855,98 +1857,110 @@ private:
 };
 
 
-class MidiPortOptions : public OptionEditorBox, public sigc::trackable
+class MidiPortOptions : public OptionEditorPageBox, public sigc::trackable
 {
-  public:
-       MidiPortOptions() {
+       public:
+               MidiPortOptions() {
 
-               setup_midi_port_view (midi_output_view, false);
-               setup_midi_port_view (midi_input_view, true);
+                       setup_midi_port_view (midi_output_view, false);
+                       setup_midi_port_view (midi_input_view, true);
 
 
-               input_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Inputs")));
-               _box->pack_start (input_label, false, false);
-               _box->pack_start (midi_input_view);
+                       _box->pack_start (*manage (new Label("")), false, false);
+                       input_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Inputs")));
+                       _box->pack_start (input_label, false, false);
 
-               output_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Outputs")));
-               _box->pack_start (output_label, false, false);
-               _box->pack_start (midi_output_view);
+                       Gtk::ScrolledWindow* scroller = manage (new Gtk::ScrolledWindow);
+                       scroller->add (midi_input_view);
+                       scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
+                       scroller->set_size_request (-1, 180);
+                       _box->pack_start (*scroller, false, false);
 
-               midi_output_view.show ();
-               midi_input_view.show ();
+                       _box->pack_start (*manage (new Label("")), false, false);
+                       output_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Outputs")));
+                       _box->pack_start (output_label, false, false);
 
-               _box->signal_show().connect (sigc::mem_fun (*this, &MidiPortOptions::on_show));
-       }
+                       scroller = manage (new Gtk::ScrolledWindow);
+                       scroller->add (midi_output_view);
+                       scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
+                       scroller->set_size_request (-1, 180);
+                       _box->pack_start (*scroller, false, false);
 
-       void parameter_changed (string const&) {}
-       void set_state_from_config() {}
+                       midi_output_view.show ();
+                       midi_input_view.show ();
 
-       void on_show () {
-               refill ();
+                       _box->signal_show().connect (sigc::mem_fun (*this, &MidiPortOptions::on_show));
+               }
 
-               AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections,
-                                                                              invalidator (*this),
-                                                                              boost::bind (&MidiPortOptions::refill, this),
-                                                                              gui_context());
-               AudioEngine::instance()->MidiPortInfoChanged.connect (connections,
-                                                                     invalidator (*this),
-                                                                     boost::bind (&MidiPortOptions::refill, this),
-                                                                     gui_context());
-               AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections,
-                                                                           invalidator (*this),
-                                                                           boost::bind (&MidiPortOptions::refill, this),
-                                                                           gui_context());
-       }
+               void parameter_changed (string const&) {}
+               void set_state_from_config() {}
 
-       void refill () {
+               void on_show () {
+                       refill ();
 
-               if (refill_midi_ports (true, midi_input_view)) {
-                       input_label.show ();
-               } else {
-                      input_label.hide ();
-               }
-               if (refill_midi_ports (false, midi_output_view)) {
-                       output_label.show ();
-               } else {
-                       output_label.hide ();
+                       AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections,
+                                       invalidator (*this),
+                                       boost::bind (&MidiPortOptions::refill, this),
+                                       gui_context());
+                       AudioEngine::instance()->MidiPortInfoChanged.connect (connections,
+                                       invalidator (*this),
+                                       boost::bind (&MidiPortOptions::refill, this),
+                                       gui_context());
+                       AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections,
+                                       invalidator (*this),
+                                       boost::bind (&MidiPortOptions::refill, this),
+                                       gui_context());
                }
-       }
-
-  private:
-       PBD::ScopedConnectionList connections;
 
-       /* MIDI port management */
-       struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
+               void refill () {
 
-               MidiPortColumns () {
-                       add (pretty_name);
-                       add (music_data);
-                       add (control_data);
-                       add (selection);
-                       add (name);
-                       add (filler);
+                       if (refill_midi_ports (true, midi_input_view)) {
+                               input_label.show ();
+                       } else {
+                               input_label.hide ();
+                       }
+                       if (refill_midi_ports (false, midi_output_view)) {
+                               output_label.show ();
+                       } else {
+                               output_label.hide ();
+                       }
                }
 
-               Gtk::TreeModelColumn<std::string> pretty_name;
-               Gtk::TreeModelColumn<bool> music_data;
-               Gtk::TreeModelColumn<bool> control_data;
-               Gtk::TreeModelColumn<bool> selection;
-               Gtk::TreeModelColumn<std::string> name;
-               Gtk::TreeModelColumn<std::string> filler;
-       };
+       private:
+               PBD::ScopedConnectionList connections;
+
+               /* MIDI port management */
+               struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
+
+                       MidiPortColumns () {
+                               add (pretty_name);
+                               add (music_data);
+                               add (control_data);
+                               add (selection);
+                               add (name);
+                               add (filler);
+                       }
 
-       MidiPortColumns midi_port_columns;
-       Gtk::TreeView midi_input_view;
-       Gtk::TreeView midi_output_view;
-       Gtk::Label input_label;
-       Gtk::Label output_label;
-
-       void setup_midi_port_view (Gtk::TreeView&, bool with_selection);
-       bool refill_midi_ports (bool for_input, Gtk::TreeView&);
-       void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*);
-       void midi_music_column_toggled (std::string const & path, Gtk::TreeView*);
-       void midi_control_column_toggled (std::string const & path, Gtk::TreeView*);
-       void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*);
+                       Gtk::TreeModelColumn<std::string> pretty_name;
+                       Gtk::TreeModelColumn<bool> music_data;
+                       Gtk::TreeModelColumn<bool> control_data;
+                       Gtk::TreeModelColumn<bool> selection;
+                       Gtk::TreeModelColumn<std::string> name;
+                       Gtk::TreeModelColumn<std::string> filler;
+               };
+
+               MidiPortColumns midi_port_columns;
+               Gtk::TreeView midi_input_view;
+               Gtk::TreeView midi_output_view;
+               Gtk::Label input_label;
+               Gtk::Label output_label;
+
+               void setup_midi_port_view (Gtk::TreeView&, bool with_selection);
+               bool refill_midi_ports (bool for_input, Gtk::TreeView&);
+               void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*);
+               void midi_music_column_toggled (std::string const & path, Gtk::TreeView*);
+               void midi_control_column_toggled (std::string const & path, Gtk::TreeView*);
+               void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*);
 };
 
 void
@@ -2011,6 +2025,8 @@ MidiPortOptions::setup_midi_port_view (Gtk::TreeView& view, bool with_selection)
 
        view.get_selection()->set_mode (SELECTION_NONE);
        view.set_tooltip_column (4); /* port "real" name */
+       view.get_column(0)->set_resizable (true);
+       view.get_column(0)->set_expand (true);
 }
 
 bool
@@ -2145,38 +2161,38 @@ MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_
 RCOptionEditor::RCOptionEditor ()
        : OptionEditorContainer (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
        , Tabbable (*this, _("Preferences")) /* pack self-as-vbox into tabbable */
-        , _rc_config (Config)
+       , _rc_config (Config)
        , _mixer_strip_visibility ("mixer-element-visibility")
 {
        UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
 
        /* MISC */
 
-        uint32_t hwcpus = hardware_concurrency ();
+       uint32_t hwcpus = hardware_concurrency ();
        BoolOption* bo;
        BoolComboOption* bco;
 
-        if (hwcpus > 1) {
-                add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
+       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)
-                        );
+               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"));
+               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 (P_("%1 processor", "%1 processors", i), i));
-                }
+               for (uint32_t i = 1; i <= hwcpus; ++i) {
+                       procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
+               }
 
                procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
 
-                add_option (_("Misc"), procs);
-        }
+               add_option (_("Misc"), procs);
+       }
 
        add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
 
@@ -2228,14 +2244,6 @@ RCOptionEditor::RCOptionEditor ()
 
        add_option (_("Misc/Click"), new ClickOptions (_rc_config));
 
-       add_option (_("Misc/Click"),
-            new FaderOption (
-                    "click-gain",
-                    _("Click gain level"),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
-                    sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
-                    ));
-
        add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
 
        add_option (_("Misc"),
@@ -2256,12 +2264,26 @@ RCOptionEditor::RCOptionEditor ()
                     1, 1000, 1, 20
                     ));
 
+       add_option (_("Misc"), new OptionEditorHeading (_("Tempo")));
+
+       BoolOption* tsf;
+
+       tsf = new BoolOption (
+               "allow-non-quarter-pulse",
+               _("Allow non quarter-note pulse"),
+               sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_allow_non_quarter_pulse),
+               sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_allow_non_quarter_pulse)
+               );
+       Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
+                                           string_compose (_("<b>When enabled</b> %1 will allow tempo to be expressed in divisions per minute\n"
+                                                             "<b>When disabled</b> %1 will only allow tempo to be expressed in quarter notes per minute"),
+                                                           PROGRAM_NAME));
+       add_option (_("Misc"), tsf);
+
        /* TRANSPORT */
 
        add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
 
-       BoolOption* tsf;
-
        tsf = new BoolOption (
                     "latched-record-enable",
                     _("Keep record-enable engaged on stop"),
@@ -2469,7 +2491,7 @@ RCOptionEditor::RCOptionEditor ()
        Gtkmm2ext::UI::instance()->set_tip
                (_ltc_send_continuously->tip_widget(),
                 string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
-       add_option (_("Transport"), _ltc_send_continuously);
+       add_option (_("Transport/Sync"), _ltc_send_continuously);
 
        _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
        _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
@@ -2484,6 +2506,8 @@ RCOptionEditor::RCOptionEditor ()
 
        /* EDITOR */
 
+       add_option (_("Editor"), new OptionEditorHeading (_("Editor Settings")));
+
        add_option (_("Editor"),
             new BoolOption (
                     "rubberbanding-snaps-to-grid",
@@ -2510,14 +2534,6 @@ RCOptionEditor::RCOptionEditor ()
                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
                     ));
 
-       add_option (_("Editor"),
-            new BoolOption (
-                    "show-editor-meter",
-                    _("Display master-meter in the toolbar"),
-                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
-                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
-                    ));
-
 if (!Profile->get_mixbus()) {
        add_option (_("Editor"),
                    new BoolOption (
@@ -2544,6 +2560,14 @@ if (!Profile->get_mixbus()) {
                            sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag)
                            ));
 
+       add_option (_("Editor"),
+                   new BoolOption (
+                           "use-double-click-to-zoom-to-selection",
+                           _("Use double mouse click to zoom to selection"),
+                           sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_double_click_to_zoom_to_selection),
+                           sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_double_click_to_zoom_to_selection)
+                           ));
+
        add_option (_("Editor"),
                    new BoolOption (
                            "update-editor-during-summary-drag",
@@ -2598,18 +2622,20 @@ if (!Profile->get_mixbus()) {
 
        add_option (_("Editor"), fadeshape);
 
+#if 1
 
        bco = new BoolComboOption (
                     "use-overlap-equivalency",
-                    _("Regions in active edit groups are edited together"),
+                    _("Regions in edit groups are edited together"),
                     _("whenever they overlap in time"),
-                    _("only if they have identical length, position and origin"),
+                    _("only if they have identical length and position"),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
                     );
 
        add_option (_("Editor"), bco);
 
+#endif
        ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
                "layer-model",
                _("Layering model"),
@@ -2701,9 +2727,9 @@ if (!Profile->get_mixbus()) {
                sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
                );
 
-        if (AudioEngine::instance()->port_engine().can_monitor_input()) {
-                mm->add (HardwareMonitoring, _("via Audio Driver"));
-        }
+       if (AudioEngine::instance()->port_engine().can_monitor_input()) {
+               mm->add (HardwareMonitoring, _("via Audio Driver"));
+       }
 
        string prog (PROGRAM_NAME);
        boost::algorithm::to_lower (prog);
@@ -3016,6 +3042,8 @@ if (!ARDOUR::Profile->get_mixbus()) {
                            sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
                            ));
 
+       add_option (_("MIDI/Ports"), new OptionEditorHeading (_("MIDI Port Options")));
+
        add_option (_("MIDI/Ports"),
                    new BoolOption (
                            "get-midi-input-follows-selection",
@@ -3110,44 +3138,25 @@ if (!ARDOUR::Profile->get_mixbus()) {
                if (manager.get_status (*i) == PluginManager::Hidden) continue;
                if (!(*i)->is_instrument()) continue;
                if ((*i)->type != ARDOUR::LV2) continue;
-               audition_synth->add((*i)->unique_id, (*i)->name);
+               if ((*i)->name.length() > 46) {
+                       audition_synth->add((*i)->unique_id, (*i)->name.substr (0, 44) + "...");
+               } else {
+                       audition_synth->add((*i)->unique_id, (*i)->name);
+               }
        }
 #endif
 
        add_option (_("MIDI"), audition_synth);
 
-       /* USER INTERACTION */
-
-       if (
-#ifdef PLATFORM_WINDOWS
-                       true
-#else
-                       getenv ("ARDOUR_BUNDLED")
-#endif
-          )
-       {
-               add_option (_("User interaction"),
-                           new BoolOption (
-                                   "enable-translation",
-                                   string_compose (_("Use translations of %1 messages\n"
-                                                     "   <i>(requires a restart of %1 to take effect)</i>\n"
-                                                     "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
-                                   sigc::ptr_fun (ARDOUR::translations_are_enabled),
-                                   sigc::ptr_fun (ARDOUR::set_translations_enabled)));
-       }
-
-       add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
-
-       add_option (_("User interaction"), new KeyboardOptions);
-
        /* Control Surfaces */
 
-       add_option (_("Control Surfaces"), new ControlSurfacesOptions);
+       add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
 
        /* VIDEO Timeline */
        add_option (_("Video"), new VideoTimelineOptions (_rc_config));
 
 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
+       add_option (_("Plugins"), new OptionEditorHeading (_("Scan/Discover")));
        add_option (_("Plugins"),
                        new RcActionButton (_("Scan for Plugins"),
                                sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
@@ -3194,6 +3203,16 @@ if (!ARDOUR::Profile->get_mixbus()) {
                        new RcActionButton (_("Scan for Plugins"),
                                sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
 
+#if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT)
+       bo = new BoolOption (
+                       "",
+                       _("Enable Mac VST support (requires restart or re-scan)"),
+                       sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst),
+                       sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst)
+                       );
+       add_option (_("Plugins/VST"), bo);
+#endif
+
        bo = new BoolOption (
                        "discover-vst-on-start",
                        _("Scan for [new] VST Plugins on Application Start"),
@@ -3336,6 +3355,9 @@ if (!ARDOUR::Profile->get_mixbus()) {
 #endif
 
        /* INTERFACE */
+#if (defined OPTIONAL_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE)
+       add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Graphics Acceleration")));
+#endif
 
 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
        BoolOption* bgc = new BoolOption (
@@ -3362,6 +3384,7 @@ if (!ARDOUR::Profile->get_mixbus()) {
        add_option (S_("Preferences|GUI"), bgo);
 #endif
 
+       add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Graphical User Interface")));
        add_option (S_("Preferences|GUI"),
             new BoolOption (
                     "use-wm-visibility",
@@ -3469,9 +3492,79 @@ if (!ARDOUR::Profile->get_mixbus()) {
                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
                     ));
 
-       add_option (S_("Preferences|GUI"),
+#ifdef ENABLE_NLS
+       OptionEditorHeading* i18n_head = new OptionEditorHeading (_("Internationalization"));
+       i18n_head->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
+
+       add_option (_("GUI/Translation"), i18n_head);
+
+       bo = new BoolOption (
+                       "enable-translation",
+                       _("Use translations"),
+                       sigc::ptr_fun (ARDOUR::translations_are_enabled),
+                       sigc::ptr_fun (ARDOUR::set_translations_enabled)
+                       );
+
+       add_option (_("GUI/Translation"), bo);
+
+       _l10n = new ComboOption<ARDOUR::LocaleMode> (
+               "locale-mode",
+               _("Localization"),
+               sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_locale_mode),
+               sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_locale_mode)
+               );
+
+       _l10n->add (ARDOUR::SET_LC_ALL, _("Set complete locale"));
+       _l10n->add (ARDOUR::SET_LC_MESSAGES, _("Enable only message translation"));
+       _l10n->add (ARDOUR::SET_LC_MESSAGES_AND_LC_NUMERIC, _("Translate messages and format numeric format"));
+       _l10n->set_note (_("This setting is provided for plugin compatibility. e.g. some plugins on some systems expect the decimal point to be a dot."));
+
+       add_option (_("GUI/Translation"), _l10n);
+       parameter_changed ("enable-translation");
+#endif // ENABLE_NLS
+
+       add_option (_("GUI/Keyboard"), new OptionEditorHeading (_("Keyboard")));
+       add_option (_("GUI/Keyboard"), new KeyboardOptions);
+
+       add_option (_("GUI/Toolbar"), new OptionEditorHeading (_("Main Transport Toolbar Items")));
+
+       add_option (_("GUI/Toolbar"),
+            new BoolOption (
+                    "show-toolbar-selclock",
+                    _("Display Selection Clock in the Toolbar"),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_selclock),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_selclock)
+                    ));
+
+       if (!ARDOUR::Profile->get_small_screen()) {
+               add_option (_("GUI/Toolbar"),
+                               new BoolOption (
+                                       "show-secondary-clock",
+                                       _("Display Secondary Clock in the Toolbar"),
+                                       sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_secondary_clock),
+                                       sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_secondary_clock)
+                                       ));
+       }
+
+       add_option (_("GUI/Toolbar"),
+            new BoolOption (
+                    "show-mini-timeline",
+                    _("Display Navigation Timeline in the Toolbar"),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_mini_timeline),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_mini_timeline)
+                    ));
+
+       add_option (_("GUI/Toolbar"),
+            new BoolOption (
+                    "show-editor-meter",
+                    _("Display Master Level Meter in the Toolbar"),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
+                    sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
+                    ));
+
+       add_option (_("GUI/Toolbar"),
                        new ColumVisibilityOption (
-                               "action-table-columns", _("Action Script Button Visibility"), 3,
+                               "action-table-columns", _("Lua Action Script Button Visibility"), 4,
                                sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_action_table_columns),
                                sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_action_table_columns)
                                )
@@ -3657,10 +3750,13 @@ if (!ARDOUR::Profile->get_mixbus()) {
        /* and now the theme manager */
 
        ThemeManager* tm = manage (new ThemeManager);
+       add_option (_("Theme"), new OptionEditorHeading (_("Theme")));
        add_page (_("Theme"), *tm);
 
        add_option (_("Theme/Colors"), new ColorThemeManager);
 
+       Widget::show_all ();
+
        //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
        parameter_changed ("send-ltc");
        parameter_changed ("sync-source");
@@ -3714,6 +3810,10 @@ RCOptionEditor::parameter_changed (string const & p)
        } else if (p == "open-gui-after-adding-plugin" || p == "show-inline-display-by-default") {
 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
                _plugin_prefer_inline->set_sensitive (UIConfiguration::instance().get_open_gui_after_adding_plugin() && UIConfiguration::instance().get_show_inline_display_by_default());
+#endif
+#ifdef ENABLE_NLS
+       } else if (p == "enable-translation") {
+               _l10n->set_sensitive (ARDOUR::translations_are_enabled ());
 #endif
        }
 }