Fix Mixbus action fc83d044f8 & 65bda27d4 rebase ordering
[ardour.git] / gtk2_ardour / mixer_ui.cc
index 88489f8cc3e5cc1e27106a597635e724cfcacdc2..b56ed4d601a1b8affb8a7d595886cd0e343ad3d0 100644 (file)
 
 #include <boost/foreach.hpp>
 
+#include <glibmm/threads.h>
+
 #include <gtkmm/accelmap.h>
+#include <gtkmm/stock.h>
 
 #include "pbd/convert.h"
 #include "pbd/stacktrace.h"
@@ -60,7 +63,6 @@
 #include "public_editor.h"
 #include "mouse_cursors.h"
 #include "ardour_ui.h"
-#include "prompter.h"
 #include "utils.h"
 #include "route_sorter.h"
 #include "actions.h"
@@ -101,19 +103,18 @@ Mixer_UI::Mixer_UI ()
        , no_track_list_redisplay (false)
        , in_group_row_change (false)
        , track_menu (0)
-       , _monitor_section (0)
        , _plugin_selector (0)
        , _strip_width (UIConfiguration::instance().get_default_narrow_ms() ? Narrow : Wide)
+       , _spill_scroll_position (0)
        , ignore_reorder (false)
        , _in_group_rebuild_or_clear (false)
        , _route_deletion_in_progress (false)
        , _maximised (false)
-       , _show_mixer_list (true)
-       , myactions (X_("mixer"))
+       , _strip_selection_change_without_scroll (false)
        , _selection (*this, *this)
 {
-       register_actions ();
        load_bindings ();
+       register_actions ();
        _content.set_data ("ardour-bindings", bindings);
 
        PresentationInfo::Change.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::presentation_info_changed, this, _1), gui_context());
@@ -132,8 +133,31 @@ Mixer_UI::Mixer_UI ()
        scroller_base.drag_dest_set (target_table);
        scroller_base.signal_drag_data_received().connect (sigc::mem_fun(*this, &Mixer_UI::scroller_drag_data_received));
 
-       // add as last item of strip packer
+       /* create a button to add VCA strips ... will get packed in redisplay_track_list() */
+       Widget* w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
+       w->show ();
+       add_vca_button.add (*w);
+       add_vca_button.set_can_focus(false);
+       add_vca_button.signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::new_track_or_bus));
+
+       /* create a button to add mixer strips */
+       w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
+       w->show ();
+       add_button.add (*w);
+       add_button.set_can_focus(false);
+       add_button.signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::new_track_or_bus));
+
+       /* add as last item of strip packer */
        strip_packer.pack_end (scroller_base, true, true);
+       strip_packer.pack_end (add_button, false, false);
+
+#ifdef MIXBUS
+       /* create a drop-shadow at the end of the mixer strips */
+       mb_shadow.set_size_request( 4, -1 );
+       mb_shadow.set_name("EditorWindow");
+       mb_shadow.show();
+       strip_packer.pack_end (mb_shadow, false, false);
+#endif
 
        _group_tabs = new MixerGroupTabs (this);
        VBox* b = manage (new VBox);
@@ -185,37 +209,13 @@ Mixer_UI::Mixer_UI ()
        group_display_scroller.add (group_display);
        group_display_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
 
-       HBox* route_group_display_button_box = manage (new HBox());
-
-       Button* route_group_add_button = manage (new Button ());
-       Button* route_group_remove_button = manage (new Button ());
-
-       Widget* w;
-
-       w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
-       w->show();
-       route_group_add_button->add (*w);
-
-       w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
-       w->show();
-       route_group_remove_button->add (*w);
-
-       route_group_display_button_box->set_homogeneous (true);
-
-       route_group_add_button->signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::new_route_group));
-       route_group_remove_button->signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::remove_selected_route_group));
-
-       route_group_display_button_box->add (*route_group_add_button);
-       route_group_display_button_box->add (*route_group_remove_button);
 
        group_display_vbox.pack_start (group_display_scroller, true, true);
-       group_display_vbox.pack_start (*route_group_display_button_box, false, false);
 
        group_display_frame.set_name ("BaseFrame");
        group_display_frame.set_shadow_type (Gtk::SHADOW_IN);
        group_display_frame.add (group_display_vbox);
 
-
        list<TargetEntry> target_list;
        target_list.push_back (TargetEntry ("PluginPresetPtr"));
 
@@ -228,7 +228,6 @@ Mixer_UI::Mixer_UI ()
        favorite_plugins_display.set_headers_visible (true);
        favorite_plugins_display.set_rules_hint (true);
        favorite_plugins_display.set_can_focus (false);
-       favorite_plugins_display.set_tooltip_column (0);
        favorite_plugins_display.add_object_drag (favorite_plugins_columns.plugin.index(), "PluginFavoritePtr");
        favorite_plugins_display.set_drag_column (favorite_plugins_columns.name.index());
        favorite_plugins_display.add_drop_targets (target_list);
@@ -237,6 +236,9 @@ Mixer_UI::Mixer_UI ()
        favorite_plugins_display.signal_drop.connect (sigc::mem_fun (*this, &Mixer_UI::plugin_drop));
        favorite_plugins_display.signal_row_expanded().connect (sigc::mem_fun (*this, &Mixer_UI::save_favorite_ui_state));
        favorite_plugins_display.signal_row_collapsed().connect (sigc::mem_fun (*this, &Mixer_UI::save_favorite_ui_state));
+       if (UIConfiguration::instance().get_use_tooltips()) {
+               favorite_plugins_display.set_tooltip_column (0);
+       }
        favorite_plugins_model->signal_row_has_child_toggled().connect (sigc::mem_fun (*this, &Mixer_UI::sync_treeview_favorite_ui_state));
 
        favorite_plugins_scroller.add (favorite_plugins_display);
@@ -244,7 +246,11 @@ Mixer_UI::Mixer_UI ()
 
        favorite_plugins_frame.set_name ("BaseFrame");
        favorite_plugins_frame.set_shadow_type (Gtk::SHADOW_IN);
-       favorite_plugins_frame.add (favorite_plugins_scroller);
+       favorite_plugins_frame.add (favorite_plugins_vbox);
+
+       favorite_plugins_vbox.pack_start (favorite_plugins_scroller, true, true);
+       favorite_plugins_vbox.pack_start (favorite_plugins_tag_combo, false, false);
+       favorite_plugins_tag_combo.signal_changed().connect (sigc::mem_fun (*this, &Mixer_UI::tag_combo_changed));
 
        rhs_pane1.add (favorite_plugins_frame);
        rhs_pane1.add (track_display_frame);
@@ -260,7 +266,6 @@ Mixer_UI::Mixer_UI ()
        vca_scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        vca_scroller_base.set_name (X_("MixerWindow"));
        vca_scroller_base.signal_button_release_event().connect (sigc::mem_fun(*this, &Mixer_UI::masters_scroller_button_release), false);
-       vca_hpacker.pack_end (vca_scroller_base, true, true);
 
        vca_scroller.add (vca_hpacker);
        vca_scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC);
@@ -277,7 +282,7 @@ Mixer_UI::Mixer_UI ()
        list_hpane.set_check_divider_position (true);
        list_hpane.add (list_vpacker);
        list_hpane.add (global_hpacker);
-       list_hpane.set_child_minsize (list_vpacker, 1);
+       list_hpane.set_child_minsize (list_vpacker, 30);
 
        XMLNode const * settings = ARDOUR_UI::instance()->mixer_settings();
        float fract;
@@ -311,10 +316,6 @@ Mixer_UI::Mixer_UI ()
 
        update_title ();
 
-       route_group_display_button_box->show();
-       route_group_add_button->show();
-       route_group_remove_button->show();
-
        _content.show ();
        _content.set_name ("MixerWindow");
 
@@ -325,7 +326,6 @@ Mixer_UI::Mixer_UI ()
        mixer_scroller_vpacker.show();
        list_vpacker.show();
        group_display_button_label.show();
-       group_display_button.show();
        group_display_scroller.show();
        favorite_plugins_scroller.show();
        group_display_vbox.show();
@@ -345,8 +345,15 @@ Mixer_UI::Mixer_UI ()
        list_hpane.show();
        group_display.show();
        favorite_plugins_display.show();
+       add_button.show ();
+
+       XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section"));
+       if (mnode) {
+               _monitor_section.tearoff().set_state (*mnode);
+       }
 
        MixerStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_strip, this, _1), gui_context());
+       VCAMasterStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_master, this, _1), gui_context());
 
        /* handle escape */
 
@@ -357,27 +364,42 @@ Mixer_UI::Mixer_UI ()
 #else
 #error implement deferred Plugin-Favorite list
 #endif
-       PluginManager::instance ().PluginListChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
-       PluginManager::instance ().PluginStatusesChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
+
+       PluginManager::instance ().PluginListChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::plugin_list_changed, this), gui_context());
+       PluginManager::instance ().PluginStatusChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::plugin_list_changed, this), gui_context());
        ARDOUR::Plugin::PresetsChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::refill_favorite_plugins, this), gui_context());
 }
 
 Mixer_UI::~Mixer_UI ()
 {
-       if (_monitor_section) {
-               monitor_section_detached ();
-               delete _monitor_section;
-       }
+       monitor_section_detached ();
+
        delete _plugin_selector;
        delete track_menu;
 }
 
+struct MixerStripSorter {
+       bool operator() (const MixerStrip* ms_a, const MixerStrip* ms_b)
+       {
+               boost::shared_ptr<ARDOUR::Stripable> const& a = ms_a->stripable ();
+               boost::shared_ptr<ARDOUR::Stripable> const& b = ms_b->stripable ();
+               return ARDOUR::Stripable::Sorter(true)(a, b);
+       }
+};
+
+
 void
 Mixer_UI::escape ()
 {
        select_none ();
 }
 
+void
+Mixer_UI::tag_combo_changed ()
+{
+       refill_favorite_plugins();
+}
+
 Gtk::Window*
 Mixer_UI::use_own_window (bool and_fill_it)
 {
@@ -533,7 +555,7 @@ Mixer_UI::add_stripables (StripableList& slist)
                                row[stripable_columns.strip] = vms;
                                row[stripable_columns.stripable] = vca;
 
-                               vms->CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::remove_master, this, _1), gui_context());
+                               vms->signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::vca_button_release_event), vms));
 
                        } else if ((route = boost::dynamic_pointer_cast<Route> (*s))) {
 
@@ -543,23 +565,14 @@ Mixer_UI::add_stripables (StripableList& slist)
 
                                if (route->is_monitor()) {
 
-                                       if (!_monitor_section) {
-                                               _monitor_section = new MonitorSection (_session);
-
-                                               XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section"));
-                                               if (mnode) {
-                                                       _monitor_section->tearoff().set_state (*mnode);
-                                               }
-                                       }
-
-                                       out_packer.pack_end (_monitor_section->tearoff(), false, false);
-                                       _monitor_section->set_session (_session);
-                                       _monitor_section->tearoff().show_all ();
+                                       out_packer.pack_end (_monitor_section.tearoff(), false, false);
+                                       _monitor_section.set_session (_session);
+                                       _monitor_section.tearoff().show_all ();
 
-                                       _monitor_section->tearoff().Detach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_detached));
-                                       _monitor_section->tearoff().Attach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_attached));
+                                       _monitor_section.tearoff().Detach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_detached));
+                                       _monitor_section.tearoff().Attach.connect (sigc::mem_fun(*this, &Mixer_UI::monitor_section_attached));
 
-                                       if (_monitor_section->tearoff().torn_off()) {
+                                       if (_monitor_section.tearoff().torn_off()) {
                                                monitor_section_detached ();
                                        } else {
                                                monitor_section_attached ();
@@ -583,7 +596,12 @@ Mixer_UI::add_stripables (StripableList& slist)
 
                                show_strip (strip);
 
-                               if (!route->is_master()) {
+                               if (route->is_master()) {
+
+                                       out_packer.pack_start (*strip, false, false);
+                                       strip->set_packed (true);
+
+                               } else {
 
                                        TreeModel::Row row = *(track_model->insert (insert_iter));
 
@@ -591,11 +609,6 @@ Mixer_UI::add_stripables (StripableList& slist)
                                        row[stripable_columns.visible] = strip->marked_for_display();
                                        row[stripable_columns.stripable] = route;
                                        row[stripable_columns.strip] = strip;
-
-                               } else {
-
-                                       out_packer.pack_start (*strip, false, false);
-                                       strip->set_packed (true);
                                }
 
                                strip->WidthChanged.connect (sigc::mem_fun(*this, &Mixer_UI::strip_width_changed));
@@ -631,16 +644,24 @@ Mixer_UI::deselect_all_strip_processors ()
 }
 
 void
-Mixer_UI::select_all_tracks ()
+Mixer_UI::select_none ()
 {
-       PublicEditor::instance().select_all_tracks ();
+       _selection.clear_routes();
+       deselect_all_strip_processors();
 }
 
 void
-Mixer_UI::select_none ()
+Mixer_UI::select_next_strip ()
 {
-       _selection.clear_routes();
        deselect_all_strip_processors();
+       _session->selection().select_next_stripable (true, false);
+}
+
+void
+Mixer_UI::select_prev_strip ()
+{
+       deselect_all_strip_processors();
+       _session->selection().select_prev_stripable (true, false);
 }
 
 void
@@ -823,9 +844,23 @@ Mixer_UI::sync_treeview_from_presentation_info (PropertyChange const & what_chan
                        }
                }
 
-               if (!_selection.axes.empty() && !PublicEditor::instance().track_selection_change_without_scroll ()) {
+               if (!_selection.axes.empty() && !PublicEditor::instance().track_selection_change_without_scroll () && !_strip_selection_change_without_scroll) {
                        move_stripable_into_view ((*_selection.axes.begin())->stripable());
                }
+
+               TreeModel::Children rows = track_model->children();
+               for (TreeModel::Children::const_iterator i = rows.begin(); i != rows.end(); ++i) {
+                       AxisView* av = (*i)[stripable_columns.strip];
+                       VCAMasterStrip* vms = dynamic_cast<VCAMasterStrip*> (av);
+                       if (!vms) {
+                               continue;
+                       }
+                       if (vms->vca() && vms->vca()->is_selected()) {
+                               _selection.add (vms);
+                       } else {
+                               _selection.remove (vms);
+                       }
+               }
        }
 
        redisplay_track_list ();
@@ -865,6 +900,15 @@ Mixer_UI::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
                }
        }
 
+       TreeModel::Children rows = track_model->children();
+       for (TreeModel::Children::const_iterator i = rows.begin(); i != rows.end(); ++i) {
+               AxisView* av = (*i)[stripable_columns.strip];
+               VCAMasterStrip* vms = dynamic_cast<VCAMasterStrip*> (av);
+               if (vms && vms->stripable () == s) {
+                       return av;
+               }
+       }
+
        return 0;
 }
 
@@ -880,18 +924,20 @@ Mixer_UI::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
        return 0;
 }
 
-struct MixerStripSorter {
-       bool operator() (const MixerStrip* ms_a, const MixerStrip* ms_b)
-       {
-               boost::shared_ptr<ARDOUR::Stripable> const& a = ms_a->stripable ();
-               boost::shared_ptr<ARDOUR::Stripable> const& b = ms_b->stripable ();
-               return ARDOUR::Stripable::Sorter(true)(a, b);
-       }
-};
-
 bool
 Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
 {
+       /* Selecting a mixer-strip may also select grouped-tracks, and
+        * presentation_info_changed() being emitted and
+        * _selection.axes.begin() is being moved into view. This may
+        * effectively move the track that was clicked-on out of view.
+        *
+        * So here only the track that is actually clicked-on is moved into
+        * view (in case it's partially visible)
+        */
+       PBD::Unwinder<bool> uw (_strip_selection_change_without_scroll, true);
+       move_stripable_into_view (strip->stripable());
+
        if (ev->button == 1) {
                if (_selection.selected (strip)) {
                        /* primary-click: toggle selection state of strip */
@@ -901,6 +947,11 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
                                /* de-select others */
                                _selection.set (strip);
                        }
+                       PublicEditor& pe = PublicEditor::instance();
+                       TimeAxisView* tav = pe.time_axis_view_from_stripable (strip->stripable());
+                       if (tav) {
+                               pe.set_selected_mixer_strip (*tav);
+                       }
                } else {
                        if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
                                _selection.add (strip, true);
@@ -965,10 +1016,18 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
        return true;
 }
 
+bool
+Mixer_UI::vca_button_release_event (GdkEventButton *ev, VCAMasterStrip *strip)
+{
+       _selection.set (strip);
+       return true;
+}
+
 void
 Mixer_UI::set_session (Session* sess)
 {
        SessionHandlePtr::set_session (sess);
+       _monitor_section.set_session (sess);
 
        if (_plugin_selector) {
                _plugin_selector->set_session (_session);
@@ -976,16 +1035,13 @@ Mixer_UI::set_session (Session* sess)
 
        _group_tabs->set_session (sess);
 
-       if (_monitor_section) {
-               _monitor_section->set_session (_session);
-       }
-
        if (!_session) {
                _selection.clear ();
                return;
        }
 
        refill_favorite_plugins();
+       refill_tag_combo();
 
        XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
        set_state (*node, 0);
@@ -1037,9 +1093,7 @@ Mixer_UI::session_going_away ()
                delete (*i);
        }
 
-       if (_monitor_section) {
-               _monitor_section->tearoff().hide_visible ();
-       }
+       _monitor_section.tearoff().hide_visible ();
 
        monitor_section_detached ();
 
@@ -1385,6 +1439,9 @@ Mixer_UI::redisplay_track_list ()
        if (ss) {
                boost::shared_ptr<VCA> sv = boost::dynamic_pointer_cast<VCA> (ss);
                if (sv) {
+                       if (_spill_scroll_position <= 0 && scroller.get_hscrollbar()) {
+                               _spill_scroll_position = scroller.get_hscrollbar()->get_adjustment()->get_value();
+                       }
                        spill_redisplay (sv);
                        return;
                }
@@ -1395,7 +1452,12 @@ Mixer_UI::redisplay_track_list ()
        uint32_t n_masters = 0;
 
        container_clear (vca_hpacker);
+
        vca_hpacker.pack_end (vca_scroller_base, true, true);
+       vca_hpacker.pack_end (add_vca_button, false, false);
+
+       add_vca_button.show ();
+       vca_scroller_base.show();
 
        for (i = rows.begin(); i != rows.end(); ++i) {
 
@@ -1450,14 +1512,35 @@ Mixer_UI::redisplay_track_list ()
        /* update visibility of VCA assign buttons */
 
        if (n_masters == 0) {
+               //show/hide the channelstrip VCA assign buttons on channelstrips:
                UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::remove_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA")));
+
+               Glib::RefPtr<Action> act = ActionManager::get_action ("Mixer", "ToggleVCAPane");
+               if (act) {
+                       act->set_sensitive (false);
+               }
+
+               //remove the VCA packer, but don't change our prior setting for show/hide:
                vca_vpacker.hide ();
        } else {
+               //show/hide the channelstrip VCA assign buttons on channelstrips:
                UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::add_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA")));
-               vca_vpacker.show ();
+
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane");
+               act->set_sensitive (true);
+
+               //if we were showing VCAs before, show them now:
+               showhide_vcas (act->get_active ());
        }
 
        _group_tabs->set_dirty ();
+
+       if (_spill_scroll_position > 0 && scroller.get_hscrollbar()) {
+               Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
+               adj->set_value (max (adj->get_lower(), min (adj->get_upper(), _spill_scroll_position)));
+       }
+       _spill_scroll_position = 0;
+
 }
 
 void
@@ -1506,18 +1589,7 @@ void
 Mixer_UI::initial_track_display ()
 {
        StripableList sl;
-
-       boost::shared_ptr<RouteList> routes = _session->get_routes();
-
-       for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
-               sl.push_back (*r);
-       }
-
-       VCAList vcas = _session->vca_manager().vcas();
-
-       for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
-               sl.push_back (boost::dynamic_pointer_cast<Stripable> (*v));
-       }
+       _session->get_stripables (sl);
 
        sl.sort (PresentationInfoMixerSorter());
 
@@ -1615,10 +1687,10 @@ Mixer_UI::build_track_menu ()
        items.push_back (MenuElem (_("Hide All"), sigc::mem_fun(*this, &Mixer_UI::hide_all_routes)));
        items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun(*this, &Mixer_UI::show_all_audiotracks)));
        items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun(*this, &Mixer_UI::hide_all_audiotracks)));
-       items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun(*this, &Mixer_UI::show_all_audiobus)));
-       items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun(*this, &Mixer_UI::hide_all_audiobus)));
        items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &Mixer_UI::show_all_miditracks)));
        items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &Mixer_UI::hide_all_miditracks)));
+       items.push_back (MenuElem (_("Show All Busses"), sigc::mem_fun(*this, &Mixer_UI::show_all_audiobus)));
+       items.push_back (MenuElem (_("Hide All Busses"), sigc::mem_fun(*this, &Mixer_UI::hide_all_audiobus)));
 
 }
 
@@ -1849,34 +1921,81 @@ Mixer_UI::route_group_property_changed (RouteGroup* group, const PropertyChange&
 }
 
 void
-Mixer_UI::show_mixer_list (bool yn)
+Mixer_UI::toggle_mixer_list ()
+{
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleMixerList");
+       showhide_mixer_list (act->get_active());
+}
+
+void
+Mixer_UI::showhide_mixer_list (bool yn)
 {
        if (yn) {
                list_vpacker.show ();
        } else {
                list_vpacker.hide ();
        }
+}
 
-       _show_mixer_list = yn;
+void
+Mixer_UI::toggle_monitor_section ()
+{
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection");
+       showhide_monitor_section (act->get_active());
 }
 
+
 void
-Mixer_UI::show_monitor_section (bool yn)
+Mixer_UI::showhide_monitor_section (bool yn)
 {
-       if (!monitor_section()) {
+       if (monitor_section().tearoff().torn_off()) {
                return;
        }
-       if (monitor_section()->tearoff().torn_off()) {
-               return;
+
+       if (yn) {
+               monitor_section().tearoff().show();
+       } else {
+               monitor_section().tearoff().hide();
        }
+}
 
+void
+Mixer_UI::toggle_vcas ()
+{
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane");
+       showhide_vcas (act->get_active());
+}
+
+void
+Mixer_UI::showhide_vcas (bool yn)
+{
        if (yn) {
-               monitor_section()->tearoff().show();
+               vca_vpacker.show();
        } else {
-               monitor_section()->tearoff().hide();
+               vca_vpacker.hide();
        }
 }
 
+#ifdef MIXBUS
+void
+Mixer_UI::toggle_mixbuses ()
+{
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleMixbusPane");
+       showhide_mixbuses (act->get_active());
+}
+
+void
+Mixer_UI::showhide_mixbuses (bool on)
+{
+       if (on) {
+               mb_vpacker.show();
+       } else {
+               mb_vpacker.hide();
+       }
+}
+#endif
+
+
 void
 Mixer_UI::route_group_name_edit (const std::string& path, const std::string& new_text)
 {
@@ -1995,7 +2114,6 @@ Mixer_UI::strip_scroller_button_release (GdkEventButton* ev)
 void
 Mixer_UI::scroller_drag_data_received (const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& data, guint info, guint time)
 {
-       printf ("Mixer_UI::scroller_drag_data_received\n");
        if (data.get_target() != "PluginFavoritePtr") {
                context->drag_finish (false, false, time);
                return;
@@ -2017,7 +2135,7 @@ Mixer_UI::scroller_drag_data_received (const Glib::RefPtr<Gdk::DragContext>& con
                if (!pip->is_instrument ()) {
                        continue;
                }
-               ARDOUR_UI::instance()->session_add_midi_track ((RouteGroup*) 0, 1, _("MIDI"), Config->get_strict_io (), pip, ppp->_preset.valid ? &ppp->_preset : 0, PresentationInfo::max_order);
+               ARDOUR_UI::instance()->session_add_midi_route (true, (RouteGroup*) 0, 1, _("MIDI"), Config->get_strict_io (), pip, ppp->_preset.valid ? &ppp->_preset : 0, PresentationInfo::max_order);
                ok = true;
        }
 
@@ -2075,39 +2193,51 @@ Mixer_UI::set_state (const XMLNode& node, int version)
        node.get_property ("show-mixer", _visible);
 
        if (node.get_property ("maximised", yn)) {
-               Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalMixer"));
-               assert (act);
-               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-               bool fs = tact && tact->get_active();
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action (X_("Common"), X_("ToggleMaximalMixer"));
+               bool fs = act && act->get_active();
                if (yn ^ fs) {
                        ActionManager::do_action ("Common", "ToggleMaximalMixer");
                }
        }
 
        if (node.get_property ("show-mixer-list", yn)) {
-               Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMixerList"));
-               assert (act);
-               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMixerList"));
 
                /* do it twice to force the change */
-               tact->set_active (!yn);
-               tact->set_active (yn);
+               act->set_active (!yn);
+               act->set_active (yn);
        }
 
        if (node.get_property ("monitor-section-visible", yn)) {
-               Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
-               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMonitorSection"));
+               /* do it twice to force the change */
+               act->set_active (!yn);
+               act->set_active (yn);
+       }
+
+       if (node.get_property ("show-vca-pane", yn)) {
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleVCAPane"));
                /* do it twice to force the change */
-               tact->set_active (yn);
-               show_monitor_section (yn);
+               act->set_active (!yn);
+               act->set_active (yn);
        }
 
+#ifdef MIXBUS
+       if (node.get_property ("show-mixbus-pane", yn)) {
+               Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleMixbusPane"));
+               /* do it twice to force the change */
+               act->set_active (!yn);
+               act->set_active (yn);
+       }
 
-       XMLNode* plugin_order;
-       if ((plugin_order = find_named_node (node, "PluginOrder")) != 0) {
+#endif
+
+       //check for the user's plugin_order file
+       XMLNode plugin_order_new(X_("PO"));
+       if (PluginManager::instance().load_plugin_order_file(plugin_order_new)) {
                store_current_favorite_order ();
                std::list<string> order;
-               const XMLNodeList& kids = plugin_order->children("PluginInfo");
+               const XMLNodeList& kids = plugin_order_new.children("PluginInfo");
                XMLNodeConstIterator i;
                for (i = kids.begin(); i != kids.end(); ++i) {
                        std::string unique_id;
@@ -2121,10 +2251,59 @@ Mixer_UI::set_state (const XMLNode& node, int version)
                PluginStateSorter cmp (order);
                favorite_order.sort (cmp);
                sync_treeview_from_favorite_order ();
+
+       } else {
+               //if there is no user file, then use an existing one from instant.xml
+               //NOTE: if you are loading an old session, this might come from the session's instant.xml
+               //Todo:  in the next major version, we should probably stop doing the instant.xml check, and just use the new file
+               XMLNode* plugin_order;
+               if ((plugin_order = find_named_node (node, "PluginOrder")) != 0) {
+                       store_current_favorite_order ();
+                       std::list<string> order;
+                       const XMLNodeList& kids = plugin_order->children("PluginInfo");
+                       XMLNodeConstIterator i;
+                       for (i = kids.begin(); i != kids.end(); ++i) {
+                               std::string unique_id;
+                               if ((*i)->get_property ("unique-id", unique_id)) {
+                                       order.push_back (unique_id);
+                                       if ((*i)->get_property ("expanded", yn)) {
+                                               favorite_ui_state[unique_id] = yn;
+                                       }
+                               }
+                       }
+
+                       PluginStateSorter cmp (order);
+                       favorite_order.sort (cmp);
+                       sync_treeview_from_favorite_order ();
+               }
        }
+
        return 0;
 }
 
+void
+Mixer_UI::save_plugin_order_file ()
+{
+       //this writes the plugin order to the user's preference file ( plugin_metadata/plugin_order )
+
+       //NOTE:  this replaces the old code that stores info in instant.xml
+       //why?  because instant.xml prefers the per-session settings, and we want this to be a global pref
+
+       store_current_favorite_order ();
+       XMLNode plugin_order ("PluginOrder");
+       uint32_t cnt = 0;
+       for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i, ++cnt) {
+               XMLNode* p = new XMLNode ("PluginInfo");
+               p->set_property ("sort", cnt);
+               p->set_property ("unique-id", (*i)->unique_id);
+               if (favorite_ui_state.find ((*i)->unique_id) != favorite_ui_state.end ()) {
+                       p->set_property ("expanded", favorite_ui_state[(*i)->unique_id]);
+               }
+               plugin_order.add_child_nocopy (*p);
+       }
+       PluginManager::instance().save_plugin_order_file( plugin_order );
+}
+
 XMLNode&
 Mixer_UI::get_state ()
 {
@@ -2139,27 +2318,21 @@ Mixer_UI::get_state ()
 
        node->set_property ("narrow-strips", (_strip_width == Narrow));
        node->set_property ("show-mixer", _visible);
-       node->set_property ("show-mixer-list", _show_mixer_list);
        node->set_property ("maximised", _maximised);
 
-       Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
-       Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-       assert (tact);
-       node->set_property ("monitor-section-visible", tact->get_active ());
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleMixerList");
+       node->set_property ("show-mixer-list", act->get_active ());
 
-       store_current_favorite_order ();
-       XMLNode* plugin_order = new XMLNode ("PluginOrder");
-       uint32_t cnt = 0;
-       for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i, ++cnt) {
-               XMLNode* p = new XMLNode ("PluginInfo");
-               p->set_property ("sort", cnt);
-               p->set_property ("unique-id", (*i)->unique_id);
-               if (favorite_ui_state.find ((*i)->unique_id) != favorite_ui_state.end ()) {
-                       p->set_property ("expanded", favorite_ui_state[(*i)->unique_id]);
-               }
-               plugin_order->add_child_nocopy (*p);
-       }
-       node->add_child_nocopy (*plugin_order);
+       act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection");
+       node->set_property ("monitor-section-visible", act->get_active ());
+
+       act = ActionManager::get_toggle_action ("Mixer", "ToggleVCAPane");
+       node->set_property ("show-vca-pane", act->get_active ());
+
+#ifdef MIXBUS
+       act = ActionManager::get_toggle_action ("Mixer", "ToggleMixbusPane");
+       node->set_property ("show-mixbus-pane", act->get_active ());
+#endif
 
        return *node;
 }
@@ -2179,6 +2352,14 @@ Mixer_UI::scroll_left ()
        using namespace Gtk::Box_Helpers;
        const BoxList& strips = strip_packer.children();
        for (BoxList::const_iterator i = strips.begin(); i != strips.end(); ++i) {
+               if (i->get_widget() == & add_button) {
+                       continue;
+               }
+#ifdef MIXBUS
+               if (i->get_widget() == &mb_shadow) {
+                       continue;
+               }
+#endif
                lm += i->get_widget()->get_width ();
                if (lm >= lp) {
                        lm -= i->get_widget()->get_width ();
@@ -2203,6 +2384,14 @@ Mixer_UI::scroll_right ()
        using namespace Gtk::Box_Helpers;
        const BoxList& strips = strip_packer.children();
        for (BoxList::const_iterator i = strips.begin(); i != strips.end(); ++i) {
+               if (i->get_widget() == & add_button) {
+                       continue;
+               }
+#ifdef MIXBUS
+               if (i->get_widget() == &mb_shadow) {
+                       continue;
+               }
+#endif
                lm += i->get_widget()->get_width ();
                if (lm > lp + 1) {
                        break;
@@ -2311,16 +2500,6 @@ Mixer_UI::setup_track_display ()
        v->show ();
        v->pack_start (track_display_scroller, true, true);
 
-       Button* b = manage (new Button);
-       b->show ();
-       Widget* w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
-       w->show ();
-       b->add (*w);
-
-       b->signal_clicked().connect (sigc::mem_fun (*this, &Mixer_UI::new_track_or_bus));
-
-       v->pack_start (*b, false, false);
-
        track_display_frame.set_name("BaseFrame");
        track_display_frame.set_shadow_type (Gtk::SHADOW_IN);
        track_display_frame.add (*v);
@@ -2403,29 +2582,27 @@ Mixer_UI::set_axis_targets_for_operation ()
 void
 Mixer_UI::monitor_section_going_away ()
 {
-       if (_monitor_section) {
-               XMLNode* ui_node = Config->extra_xml(X_("UI"));
-               /* immediate state save.
-                *
-                * Tearoff settings are otherwise only stored during
-                * save_ardour_state(). The mon-section may or may not
-                * exist at that point.
-                * */
-               if (ui_node) {
-                       XMLNode* tearoff_node = ui_node->child (X_("Tearoffs"));
-                       if (tearoff_node) {
-                               tearoff_node->remove_nodes_and_delete (X_("monitor-section"));
-                               XMLNode* t = new XMLNode (X_("monitor-section"));
-                               _monitor_section->tearoff().add_state (*t);
-                               tearoff_node->add_child_nocopy (*t);
-                       }
+       XMLNode* ui_node = Config->extra_xml(X_("UI"));
+
+       /* immediate state save.
+        *
+        * Tearoff settings are otherwise only stored during
+        * save_ardour_state(). The mon-section may or may not
+        * exist at that point.
+        */
+
+       if (ui_node) {
+               XMLNode* tearoff_node = ui_node->child (X_("Tearoffs"));
+               if (tearoff_node) {
+                       tearoff_node->remove_nodes_and_delete (X_("monitor-section"));
+                       XMLNode* t = new XMLNode (X_("monitor-section"));
+                       _monitor_section.tearoff().add_state (*t);
+                       tearoff_node->add_child_nocopy (*t);
                }
-               monitor_section_detached ();
-               out_packer.remove (_monitor_section->tearoff());
-               _monitor_section->set_session (0);
-               delete _monitor_section;
-               _monitor_section = 0;
        }
+
+       monitor_section_detached ();
+       out_packer.remove (_monitor_section.tearoff());
 }
 
 void
@@ -2481,16 +2658,15 @@ Mixer_UI::restore_mixer_space ()
 void
 Mixer_UI::monitor_section_attached ()
 {
-       Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
-       Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+       Glib::RefPtr<ToggleAction> act = ActionManager::get_toggle_action ("Mixer", "ToggleMonitorSection");
        act->set_sensitive (true);
-       show_monitor_section (tact->get_active ());
+       showhide_monitor_section (act->get_active ());
 }
 
 void
 Mixer_UI::monitor_section_detached ()
 {
-       Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
+       Glib::RefPtr<Action> act = ActionManager::get_action ("Mixer", "ToggleMonitorSection");
        act->set_sensitive (false);
 }
 
@@ -2524,9 +2700,24 @@ Mixer_UI::refiller (PluginInfoList& result, const PluginInfoList& plugs)
 {
        PluginManager& manager (PluginManager::instance());
        for (PluginInfoList::const_iterator i = plugs.begin(); i != plugs.end(); ++i) {
+
+               /* not a Favorite? skip it */
                if (manager.get_status (*i) != PluginManager::Favorite) {
                        continue;
                }
+
+               /* Check the tag combo selection, and skip this plugin if it doesn't match the selected tag(s) */
+               string test = favorite_plugins_tag_combo.get_active_text();
+               if (test != _("Show All")) {
+                       vector<string> tags = manager.get_tags(*i);
+
+                       //does the selected tag match any of the tags in the plugin?
+                       vector<string>::iterator tt =  find (tags.begin(), tags.end(), test);
+                       if (tt == tags.end()) {
+                               continue;
+                       }
+               }
+
                result.push_back (*i);
        }
 }
@@ -2589,6 +2780,30 @@ Mixer_UI::refill_favorite_plugins ()
        sync_treeview_from_favorite_order ();
 }
 
+void
+Mixer_UI::plugin_list_changed ()
+{
+       refill_favorite_plugins();
+       refill_tag_combo();
+}
+
+void
+Mixer_UI::refill_tag_combo ()
+{
+       PluginManager& mgr (PluginManager::instance());
+
+       std::vector<std::string> tags = mgr.get_all_tags (PluginManager::OnlyFavorites);
+
+       favorite_plugins_tag_combo.clear();
+       favorite_plugins_tag_combo.append_text (_("Show All"));
+
+       for (vector<string>::iterator t = tags.begin (); t != tags.end (); ++t) {
+               favorite_plugins_tag_combo.append_text (*t);
+       }
+
+       favorite_plugins_tag_combo.set_active_text (_("Show All"));
+}
+
 void
 Mixer_UI::sync_treeview_favorite_ui_state (const TreeModel::Path& path, const TreeModel::iterator&)
 {
@@ -2675,7 +2890,7 @@ Mixer_UI::popup_note_context_menu (GdkEventButton *ev)
 bool
 Mixer_UI::plugin_row_button_press (GdkEventButton *ev)
 {
-       if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3) ) {
+       if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3)) {
                TreeModel::Path path;
                TreeViewColumn* column;
                int cellx, celly;
@@ -2900,48 +3115,52 @@ Mixer_UI::showing_spill_for (boost::shared_ptr<Stripable> s) const
        return s == spilled_strip.lock();
 }
 
-void
-Mixer_UI::show_editor_window () const
-{
-       PublicEditor::instance().make_visible ();
-}
-
 void
 Mixer_UI::register_actions ()
 {
-       Glib::RefPtr<ActionGroup> group = myactions.create_action_group (X_("Mixer"));
+       Glib::RefPtr<ActionGroup> group = ActionManager::create_action_group (bindings, X_("Mixer"));
 
-       myactions.register_action (group, "show-editor", _("Show Editor"), sigc::mem_fun (*this, &Mixer_UI::show_editor_window));
+       ActionManager::register_action (group, "solo", _("Toggle Solo on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::solo_action));
+       ActionManager::register_action (group, "mute", _("Toggle Mute on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::mute_action));
+       ActionManager::register_action (group, "recenable", _("Toggle Rec-enable on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::rec_enable_action));
+       ActionManager::register_action (group, "increment-gain", _("Decrease Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::step_gain_up_action));
+       ActionManager::register_action (group, "decrement-gain", _("Increase Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::step_gain_down_action));
+       ActionManager::register_action (group, "unity-gain", _("Set Gain to 0dB on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::unity_gain_action));
 
-       myactions.register_action (group, "solo", _("Toggle Solo on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::solo_action));
-       myactions.register_action (group, "mute", _("Toggle Mute on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::mute_action));
-       myactions.register_action (group, "recenable", _("Toggle Rec-enable on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::rec_enable_action));
-       myactions.register_action (group, "increment-gain", _("Decrease Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::step_gain_up_action));
-       myactions.register_action (group, "decrement-gain", _("Increase Gain on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::step_gain_down_action));
-       myactions.register_action (group, "unity-gain", _("Set Gain to 0dB on Mixer-Selected Tracks/Busses"), sigc::mem_fun (*this, &Mixer_UI::unity_gain_action));
 
+       ActionManager::register_action (group, "copy-processors", _("Copy Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::copy_processors));
+       ActionManager::register_action (group, "cut-processors", _("Cut Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::cut_processors));
+       ActionManager::register_action (group, "paste-processors", _("Paste Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::paste_processors));
+       ActionManager::register_action (group, "delete-processors", _("Delete Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::delete_processors));
+       ActionManager::register_action (group, "select-all-processors", _("Select All (visible) Processors"), sigc::mem_fun (*this, &Mixer_UI::select_all_processors));
+       ActionManager::register_action (group, "toggle-processors", _("Toggle Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::toggle_processors));
+       ActionManager::register_action (group, "ab-plugins", _("Toggle Selected Plugins"), sigc::mem_fun (*this, &Mixer_UI::ab_plugins));
+       ActionManager::register_action (group, "select-none", _("Deselect all strips and processors"), sigc::mem_fun (*this, &Mixer_UI::select_none));
 
-       myactions.register_action (group, "copy-processors", _("Copy Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::copy_processors));
-       myactions.register_action (group, "cut-processors", _("Cut Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::cut_processors));
-       myactions.register_action (group, "paste-processors", _("Paste Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::paste_processors));
-       myactions.register_action (group, "delete-processors", _("Delete Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::delete_processors));
-       myactions.register_action (group, "select-all-processors", _("Select All (visible) Processors"), sigc::mem_fun (*this, &Mixer_UI::select_all_processors));
-       myactions.register_action (group, "toggle-processors", _("Toggle Selected Processors"), sigc::mem_fun (*this, &Mixer_UI::toggle_processors));
-       myactions.register_action (group, "ab-plugins", _("Toggle Selected Plugins"), sigc::mem_fun (*this, &Mixer_UI::ab_plugins));
-       myactions.register_action (group, "select-none", _("Deselect all strips and processors"), sigc::mem_fun (*this, &Mixer_UI::select_none));
-       myactions.register_action (group, "select-all-tracks", _("Select All Tracks"), sigc::mem_fun (*this, &Mixer_UI::select_all_tracks));
+       ActionManager::register_action (group, "select-next-stripable", _("Select Next Mixer Strip"), sigc::mem_fun (*this, &Mixer_UI::select_next_strip));
+       ActionManager::register_action (group, "select-prev-stripable", _("Scroll Previous Mixer Strip"), sigc::mem_fun (*this, &Mixer_UI::select_prev_strip));
 
-       myactions.register_action (group, "scroll-left", _("Scroll Mixer Window to the left"), sigc::mem_fun (*this, &Mixer_UI::scroll_left));
-       myactions.register_action (group, "scroll-right", _("Scroll Mixer Window to the right"), sigc::mem_fun (*this, &Mixer_UI::scroll_right));
+       ActionManager::register_action (group, "scroll-left", _("Scroll Mixer Window to the left"), sigc::mem_fun (*this, &Mixer_UI::scroll_left));
+       ActionManager::register_action (group, "scroll-right", _("Scroll Mixer Window to the right"), sigc::mem_fun (*this, &Mixer_UI::scroll_right));
 
-       myactions.register_action (group, "toggle-midi-input-active", _("Toggle MIDI Input Active for Mixer-Selected Tracks/Busses"),
+       ActionManager::register_action (group, "toggle-midi-input-active", _("Toggle MIDI Input Active for Mixer-Selected Tracks/Busses"),
                                   sigc::bind (sigc::mem_fun (*this, &Mixer_UI::toggle_midi_input_active), false));
+
+       ActionManager::register_toggle_action (group, X_("ToggleMixerList"), _("Mixer: Show Mixer List"), sigc::mem_fun (*this, &Mixer_UI::toggle_mixer_list));
+
+       ActionManager::register_toggle_action (group, X_("ToggleVCAPane"), _("Mixer: Show VCAs"), sigc::mem_fun (*this, &Mixer_UI::toggle_vcas));
+
+#ifdef MIXBUS
+       ActionManager::register_toggle_action (group, X_("ToggleMixbusPane"), _("Mixer: Show Mixbuses"), sigc::mem_fun (*this, &Mixer_UI::toggle_mixbuses));
+#endif
+
+       ActionManager::register_toggle_action (group, X_("ToggleMonitorSection"), _("Mixer: Show Monitor Section"), sigc::mem_fun (*this, &Mixer_UI::toggle_monitor_section));
 }
 
 void
 Mixer_UI::load_bindings ()
 {
-       bindings = Bindings::get_bindings (X_("Mixer"), myactions);
+       bindings = Bindings::get_bindings (X_("Mixer"));
 }
 
 template<class T> void