X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmixer_ui.cc;h=6f11e59900beeead23a65ccb3f4760125cc6db51;hb=c46cd91d0eca0e060d3efed5162c8a5205567274;hp=c775b9b2b9b4dc8b16d4bee92d6a9d276370ab92;hpb=5fc037cbe937113d571ad1427635afd41f8e6f3d;p=ardour.git diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index c775b9b2b9..6f11e59900 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -27,21 +27,15 @@ #include +#include + #include +#include #include "pbd/convert.h" #include "pbd/stacktrace.h" #include "pbd/unwind.h" -#include - -#include -#include -#include -#include -#include -#include - #include "ardour/amp.h" #include "ardour/debug.h" #include "ardour/audio_track.h" @@ -53,6 +47,14 @@ #include "ardour/vca.h" #include "ardour/vca_manager.h" +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/keyboard.h" +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/window_title.h" +#include "gtkmm2ext/doi.h" + +#include "widgets/tearoff.h" + #include "keyboard.h" #include "mixer_ui.h" #include "mixer_strip.h" @@ -61,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" @@ -110,6 +111,7 @@ Mixer_UI::Mixer_UI () , _route_deletion_in_progress (false) , _maximised (false) , _show_mixer_list (true) + , _strip_selection_change_without_scroll (false) , myactions (X_("mixer")) , _selection (*this, *this) { @@ -133,8 +135,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); @@ -186,37 +211,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 target_list; target_list.push_back (TargetEntry ("PluginPresetPtr")); @@ -245,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); @@ -261,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); @@ -278,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; @@ -312,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"); @@ -326,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(); @@ -346,8 +345,10 @@ Mixer_UI::Mixer_UI () list_hpane.show(); group_display.show(); favorite_plugins_display.show(); + add_button.show (); 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 */ @@ -358,8 +359,9 @@ 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()); } @@ -373,12 +375,28 @@ Mixer_UI::~Mixer_UI () delete track_menu; } +struct MixerStripSorter { + bool operator() (const MixerStrip* ms_a, const MixerStrip* ms_b) + { + boost::shared_ptr const& a = ms_a->stripable (); + boost::shared_ptr 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) { @@ -534,7 +552,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 (*s))) { @@ -584,7 +602,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)); @@ -592,11 +615,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)); @@ -638,6 +656,62 @@ Mixer_UI::select_none () deselect_all_strip_processors(); } + void +Mixer_UI::select_next_strip () +{ + deselect_all_strip_processors(); + strips.sort (MixerStripSorter()); + + if (_selection.empty()) { + _selection.set (strips.front()); + return; + } + + bool select_me = false; + + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + + if (select_me) { + _selection.set (*i); + return; + } + + if ((*i)->selected()) { + select_me = true; + } + } + + _selection.set (strips.front()); +} + +void +Mixer_UI::select_prev_strip () +{ + deselect_all_strip_processors(); + strips.sort (MixerStripSorter()); + + if (_selection.empty()) { + _selection.set (strips.back()); + return; + } + + bool select_me = false; + + for (list::reverse_iterator i = strips.rbegin(); i != strips.rend(); ++i) { + + if (select_me) { + _selection.set (*i); + return; + } + + if ((*i)->selected()) { + select_me = true; + } + } + + _selection.set (strips.back()); +} + void Mixer_UI::delete_processors () { @@ -818,9 +892,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 (av); + if (!vms) { + continue; + } + if (vms->vca() && vms->vca()->is_selected()) { + _selection.add (vms); + } else { + _selection.remove (vms); + } + } } redisplay_track_list (); @@ -860,6 +948,15 @@ Mixer_UI::axis_view_by_stripable (boost::shared_ptr 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 (av); + if (vms && vms->stripable () == s) { + return av; + } + } + return 0; } @@ -875,30 +972,37 @@ Mixer_UI::axis_view_by_control (boost::shared_ptr c) const return 0; } -struct MixerStripSorter { - bool operator() (const MixerStrip* ms_a, const MixerStrip* ms_b) - { - boost::shared_ptr const& a = ms_a->stripable (); - boost::shared_ptr 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 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 */ if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - _selection.remove (strip); + _selection.remove (strip, true); } else if (_selection.axes.size() > 1) { /* 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); + _selection.add (strip, true); } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) { /* extend selection */ @@ -946,7 +1050,7 @@ Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip) if (found_another) { PresentationInfo::ChangeSuspender cs; for (vector::iterator i = tmp.begin(); i != tmp.end(); ++i) { - _selection.add (*i); + _selection.add (*i, true); } } else { _selection.set (strip); //user wants to start a range selection, but there aren't any others selected yet @@ -960,6 +1064,13 @@ 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) { @@ -981,6 +1092,7 @@ Mixer_UI::set_session (Session* sess) } refill_favorite_plugins(); + refill_tag_combo(); XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); set_state (*node, 0); @@ -1390,7 +1502,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) { @@ -1447,9 +1564,22 @@ Mixer_UI::redisplay_track_list () if (n_masters == 0) { UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::remove_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA"))); vca_vpacker.hide (); + Glib::RefPtr act = ActionManager::get_action ("Common", "ToggleVCAPane"); + if (act) { + act->set_sensitive (false); + } + } else { UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::add_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA"))); - vca_vpacker.show (); + + Glib::RefPtr act = ActionManager::get_action ("Common", "ToggleVCAPane"); + if (act) { + act->set_sensitive (true); + Glib::RefPtr tact = Glib::RefPtr::cast_dynamic(act); + showhide_vcas (tact->get_active()); + } else { + vca_vpacker.show (); + } } _group_tabs->set_dirty (); @@ -1990,7 +2120,6 @@ Mixer_UI::strip_scroller_button_release (GdkEventButton* ev) void Mixer_UI::scroller_drag_data_received (const Glib::RefPtr& 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; @@ -2012,7 +2141,7 @@ Mixer_UI::scroller_drag_data_received (const Glib::RefPtr& 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; } @@ -2097,12 +2226,12 @@ Mixer_UI::set_state (const XMLNode& node, int version) show_monitor_section (yn); } - - XMLNode* plugin_order; - if ((plugin_order = find_named_node (node, "PluginOrder")) != 0) { + //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 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; @@ -2116,10 +2245,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 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 () { @@ -2142,20 +2320,6 @@ Mixer_UI::get_state () assert (tact); node->set_property ("monitor-section-visible", tact->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); - return *node; } @@ -2174,6 +2338,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 (); @@ -2198,6 +2370,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; @@ -2306,16 +2486,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); @@ -2519,9 +2689,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 tags = manager.get_tags(*i); + + //does the selected tag match any of the tags in the plugin? + vector::iterator tt = find (tags.begin(), tags.end(), test); + if (tt == tags.end()) { + continue; + } + } + result.push_back (*i); } } @@ -2584,6 +2769,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 tags = mgr.get_all_tags (PluginManager::OnlyFavorites); + + favorite_plugins_tag_combo.clear(); + favorite_plugins_tag_combo.append_text (_("Show All")); + + for (vector::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&) { @@ -2670,7 +2879,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; @@ -2925,6 +3134,9 @@ Mixer_UI::register_actions () 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-next-stripable", _("Select Next Mixer Strip"), sigc::mem_fun (*this, &Mixer_UI::select_next_strip)); + myactions.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));