X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fplugin_selector.cc;h=d3cad6520d1b3b55652772658e475e0923127b6b;hb=9a45e0fde9eb6297ea4cc246aa2ef5d085ebe49b;hp=9c03bd5c4810c9a46577a212ee112ec05fedd553;hpb=d135c4dc3a307d0be606f3afbbc8fd8c3ec56438;p=ardour.git diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc index 9c03bd5c48..d3cad6520d 100644 --- a/gtk2_ardour/plugin_selector.cc +++ b/gtk2_ardour/plugin_selector.cc @@ -36,17 +36,19 @@ #include "ardour/plugin_manager.h" #include "ardour/plugin.h" +#include "ardour/utils.h" -#include "ardour_ui.h" #include "plugin_selector.h" #include "gui_thread.h" +#include "tooltips.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; using namespace PBD; using namespace Gtk; using namespace std; +using namespace ARDOUR_UI_UTILS; static const char* _filter_mode_strings[] = { N_("Name contains"), @@ -62,8 +64,16 @@ static const char* _filter_mode_strings[] = { PluginSelector::PluginSelector (PluginManager& mgr) : ArdourDialog (_("Plugin Manager"), true, false) , filter_button (Stock::CLEAR) + , fil_hidden_button (ArdourButton::led_default_elements) + , fil_instruments_button (ArdourButton::default_elements) + , fil_analysis_button (ArdourButton::default_elements) + , fil_utils_button (ArdourButton::default_elements) , manager (mgr) - + , _show_hidden (false) + , _show_instruments (Gtkmm2ext::ImplicitActive) + , _show_analysers (Gtkmm2ext::Off) + , _show_utils (Gtkmm2ext::Off) + { set_name ("PluginSelectorWindow"); add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); @@ -72,6 +82,9 @@ PluginSelector::PluginSelector (PluginManager& mgr) in_row_change = false; manager.PluginListChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context()); + manager.PluginListChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::refill, this), gui_context()); + manager.PluginStatusesChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context()); + manager.PluginStatusesChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::refill, this), gui_context()); build_plugin_menu (); plugin_model = Gtk::ListStore::create (plugin_columns); @@ -94,6 +107,11 @@ PluginSelector::PluginSelector (PluginManager& mgr) plugin_display.set_headers_clickable (true); plugin_display.set_reorderable (false); plugin_display.set_rules_hint (true); + plugin_display.add_object_drag (plugin_columns.plugin.index(), "PluginInfoPtr"); + plugin_display.set_drag_column (plugin_columns.name.index()); + + // setting a sort-column prevents re-ordering via Drag/Drop + plugin_model->set_sort_column (plugin_columns.name.index(), Gtk::SORT_ASCENDING); CellRendererToggle* fav_cell = dynamic_cast(plugin_display.get_column_cell_renderer (0)); fav_cell->property_activatable() = true; @@ -124,53 +142,97 @@ PluginSelector::PluginSelector (PluginManager& mgr) ascroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); ascroller.add(added_list); btn_add = manage(new Gtk::Button(Stock::ADD)); - ARDOUR_UI::instance()->set_tip(*btn_add, _("Add a plugin to the effect list")); + set_tooltip(*btn_add, _("Add a plugin to the effect list")); btn_add->set_sensitive (false); btn_remove = manage(new Gtk::Button(Stock::REMOVE)); btn_remove->set_sensitive (false); - ARDOUR_UI::instance()->set_tip(*btn_remove, _("Remove a plugin from the effect list")); - Gtk::Button *btn_update = manage(new Gtk::Button(Stock::REFRESH)); - ARDOUR_UI::instance()->set_tip(*btn_update, _("Update available plugins")); + set_tooltip(*btn_remove, _("Remove a plugin from the effect list")); btn_add->set_name("PluginSelectorButton"); btn_remove->set_name("PluginSelectorButton"); + Gtk::Table* table = manage(new Gtk::Table(7, 11)); table->set_size_request(750, 500); - table->attach(scroller, 0, 7, 0, 5); - HBox* filter_box = manage (new HBox); + Gtk::Table* filter_table = manage(new Gtk::Table(2, 5)); + + fil_hidden_button.set_name ("pluginlist hide button"); + fil_hidden_button.set_text (_("Show Hidden")); + fil_hidden_button.set_active (_show_hidden); + set_tooltip (fil_hidden_button, _("Include hidden plugins in list.")); + + fil_instruments_button.set_name ("pluginlist filter button"); + fil_instruments_button.set_text (_("Instruments")); + fil_instruments_button.set_active_state (_show_instruments); + set_tooltip (fil_instruments_button, _("Cycle display of instrument plugins (if any).")); + + fil_analysis_button.set_name ("pluginlist filter button"); + fil_analysis_button.set_text (_("Analyzers")); + fil_analysis_button.set_active_state (_show_analysers); + set_tooltip (fil_analysis_button, _("Cycle display of analysis plugins (if any).")); + + fil_utils_button.set_name ("pluginlist filter button"); + fil_utils_button.set_text (_("Utils")); + fil_utils_button.set_active_state (_show_utils); + set_tooltip (fil_utils_button, _("Cycle display of utility plugins (if any).")); vector filter_strings = I18N (_filter_mode_strings); Gtkmm2ext::set_popdown_strings (filter_mode, filter_strings); filter_mode.set_active_text (filter_strings.front()); - filter_box->pack_start (filter_mode, false, false); - filter_box->pack_start (filter_entry, true, true); - filter_box->pack_start (filter_button, false, false); + fil_hidden_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_hidden_button_release), false); + fil_instruments_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_instruments_button_release), false); + fil_analysis_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_analysis_button_release), false); + fil_utils_button.signal_button_release_event().connect (sigc::mem_fun(*this, &PluginSelector::fil_utils_button_release), false); filter_entry.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_entry_changed)); filter_button.signal_clicked().connect (sigc::mem_fun (*this, &PluginSelector::filter_button_clicked)); filter_mode.signal_changed().connect (sigc::mem_fun (*this, &PluginSelector::filter_mode_changed)); - filter_box->show (); - filter_mode.show (); - filter_entry.show (); - filter_button.show (); + filter_table->attach (filter_mode, 0, 1, 0, 1, FILL, FILL); + filter_table->attach (filter_entry, 1, 4, 0, 1, FILL|EXPAND, FILL); + filter_table->attach (filter_button, 4, 5, 0, 1, FILL, FILL); + + filter_table->attach (fil_hidden_button, 1, 2, 1, 2, FILL, FILL); + filter_table->attach (fil_instruments_button, 2, 3, 1, 2, FILL, FILL); + filter_table->attach (fil_analysis_button, 3, 4, 1, 2, FILL, FILL); + filter_table->attach (fil_utils_button, 4, 5, 1, 2, FILL, FILL); + + filter_table->set_border_width (4); + filter_table->set_col_spacings (2); + filter_table->set_row_spacings (4); + + Frame* filter_frame = manage (new Frame); + filter_frame->set_name ("BaseFrame"); + filter_frame->set_label (_("Filter")); + filter_frame->add (*filter_table); + + filter_frame->show_all (); + + HBox* side_by_side = manage (new HBox); + VBox* right_side = manage (new VBox); + + table->attach (scroller, 0, 7, 0, 5); + table->attach (*filter_frame, 0, 7, 6, 7, FILL|EXPAND, FILL, 5, 5); + + right_side->pack_start (ascroller); - table->attach (*filter_box, 0, 7, 5, 6, FILL|EXPAND, FILL, 5, 5); + HBox* add_remove = manage (new HBox); + add_remove->pack_start (*btn_add, true, true); + add_remove->pack_start (*btn_remove, true, true); - table->attach(*btn_add, 1, 2, 6, 7, FILL, FILL, 5, 5); - table->attach(*btn_remove, 3, 4, 6, 7, FILL, FILL, 5, 5); - table->attach(*btn_update, 5, 6, 6, 7, FILL, FILL, 5, 5); + right_side->pack_start (*add_remove, false, false); + right_side->set_size_request (200, -1); - table->attach(ascroller, 0, 7, 8, 10); + side_by_side->pack_start (*table); + side_by_side->pack_start (*right_side); add_button (Stock::CLOSE, RESPONSE_CLOSE); add_button (_("Insert Plugin(s)"), RESPONSE_APPLY); set_default_response (RESPONSE_APPLY); set_response_sensitive (RESPONSE_APPLY, false); - get_vbox()->pack_start (*table); + get_vbox()->pack_start (*side_by_side); table->set_name("PluginSelectorTable"); plugin_display.set_name("PluginSelectorDisplay"); @@ -181,10 +243,10 @@ PluginSelector::PluginSelector (PluginManager& mgr) plugin_display.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &PluginSelector::display_selection_changed)); plugin_display.grab_focus(); - btn_update->signal_clicked().connect (sigc::mem_fun(*this, &PluginSelector::btn_update_clicked)); btn_add->signal_clicked().connect(sigc::mem_fun(*this, &PluginSelector::btn_add_clicked)); btn_remove->signal_clicked().connect(sigc::mem_fun(*this, &PluginSelector::btn_remove_clicked)); added_list.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &PluginSelector::added_list_selection_changed)); + added_list.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::added_row_clicked)); refill (); } @@ -200,6 +262,13 @@ PluginSelector::row_activated(Gtk::TreeModel::Path, Gtk::TreeViewColumn*) btn_add_clicked(); } +void +PluginSelector::added_row_clicked(GdkEventButton* event) +{ + if (event->type == GDK_2BUTTON_PRESS) + btn_remove_clicked(); +} + bool PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& filterstr) { @@ -214,6 +283,40 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& return manager.get_status (info) == PluginManager::Hidden; } + if (!_show_hidden && manager.get_status (info) == PluginManager::Hidden) { + return false; + } + + if (_show_instruments == Gtkmm2ext::Off && info->is_instrument()) { + return false; + } + if (_show_analysers == Gtkmm2ext::Off && info->in_category ("Analyser")) { + return false; + } + if (_show_utils == Gtkmm2ext::Off && info->in_category ("Utility")) { + return false; + } + + /* NB once lilv_node_as_string() does honor translation AND + * the lv2 onthology provides localized class name, + * PluginInfo will need methods for Util & Analysis. + */ + bool exp_ok = false; + if (_show_instruments == Gtkmm2ext::ExplicitActive && info->is_instrument()) { + exp_ok = true; + } + if (_show_analysers == Gtkmm2ext::ExplicitActive && info->in_category ("Analyser")) { + exp_ok = true; + } + if (_show_utils == Gtkmm2ext::ExplicitActive && info->in_category ("Utility")) { + exp_ok = true; + } + if (_show_instruments == Gtkmm2ext::ExplicitActive || _show_analysers == Gtkmm2ext::ExplicitActive || _show_utils == Gtkmm2ext::ExplicitActive) { + if (!exp_ok) { + return false; + } + } + if (!filterstr.empty()) { if (mode == _("Name contains")) { @@ -238,6 +341,12 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string& case LXVST: compstr = X_("LXVST"); break; + case MacVST: + compstr = X_("MacVST"); + break; + case Lua: + compstr = X_("Lua"); + break; } } else if (mode == _("Author contains")) { @@ -284,7 +393,9 @@ PluginSelector::refill () lv2_refiller (filterstr); vst_refiller (filterstr); lxvst_refiller (filterstr); + mac_vst_refiller (filterstr); au_refiller (filterstr); + lua_refiller (filterstr); in_row_change = false; } @@ -308,10 +419,23 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte string creator = (*i)->creator; string::size_type pos = 0; - /* stupid LADSPA creator strings */ - - while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; - creator = creator.substr (0, pos); + if ((*i)->type == ARDOUR::LADSPA) { + /* stupid LADSPA creator strings */ +#ifdef PLATFORM_WINDOWS + while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#else + while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#endif + } else { + pos = creator.length (); + } + // If there were too few characters to create a + // meaningful name, mark this creator as 'Unknown' + if (creator.length() < 2 || pos < 3) { + creator = "Unknown"; + } else{ + creator = creator.substr (0, pos); + } newrow[plugin_columns.creator] = creator; @@ -325,7 +449,7 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte newrow[plugin_columns.audio_ins] = buf; snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi()); newrow[plugin_columns.midi_ins] = buf; - + snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_audio()); newrow[plugin_columns.audio_outs] = buf; snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_midi()); @@ -343,6 +467,12 @@ PluginSelector::ladspa_refiller (const std::string& filterstr) refiller (manager.ladspa_plugin_info(), filterstr, "LADSPA"); } +void +PluginSelector::lua_refiller (const std::string& filterstr) +{ + refiller (manager.lua_plugin_info(), filterstr, "Lua"); +} + void PluginSelector::lv2_refiller (const std::string& filterstr) { @@ -375,6 +505,18 @@ PluginSelector::lxvst_refiller (const std::string&) #endif } +void +#ifdef MACVST_SUPPORT +PluginSelector::mac_vst_refiller (const std::string& filterstr) +#else +PluginSelector::mac_vst_refiller (const std::string&) +#endif +{ +#ifdef MACVST_SUPPORT + refiller (manager.mac_vst_plugin_info(), filterstr, "MacVST"); +#endif +} + void #ifdef AUDIOUNIT_SUPPORT PluginSelector::au_refiller (const std::string& filterstr) @@ -428,13 +570,6 @@ PluginSelector::btn_remove_clicked() } } -void -PluginSelector::btn_update_clicked() -{ - manager.refresh (); - refill(); -} - void PluginSelector::display_selection_changed() { @@ -519,8 +654,18 @@ PluginSelector::filter_mode_changed () if (mode == _("Favorites only") || mode == _("Hidden only")) { filter_entry.set_sensitive (false); + filter_button.set_sensitive (false); + fil_hidden_button.set_sensitive (false); + fil_instruments_button.set_sensitive (false); + fil_analysis_button.set_sensitive (false); + fil_utils_button.set_sensitive (false); } else { filter_entry.set_sensitive (true); + filter_button.set_sensitive (true); + fil_hidden_button.set_sensitive (true); + fil_instruments_button.set_sensitive (true); + fil_analysis_button.set_sensitive (true); + fil_utils_button.set_sensitive (true); } refill (); @@ -537,13 +682,13 @@ struct PluginMenuCompareByCreator { bool operator() (PluginInfoPtr a, PluginInfoPtr b) const { int cmp; - cmp = g_strcasecmp (a->creator.c_str(), b->creator.c_str()); + cmp = cmp_nocase_utf8 (a->creator, b->creator); if (cmp < 0) { return true; } else if (cmp == 0) { /* same creator ... compare names */ - if (g_strcasecmp (a->name.c_str(), b->name.c_str()) < 0) { + if (cmp_nocase_utf8 (a->name, b->name) < 0) { return true; } } @@ -555,7 +700,7 @@ struct PluginMenuCompareByName { bool operator() (PluginInfoPtr a, PluginInfoPtr b) const { int cmp; - cmp = g_strcasecmp (a->name.c_str(), b->name.c_str()); + cmp = cmp_nocase_utf8 (a->name, b->name); if (cmp < 0) { return true; @@ -573,13 +718,13 @@ struct PluginMenuCompareByCategory { bool operator() (PluginInfoPtr a, PluginInfoPtr b) const { int cmp; - cmp = g_strcasecmp (a->category.c_str(), b->category.c_str()); + cmp = cmp_nocase_utf8 (a->category, b->category); if (cmp < 0) { return true; } else if (cmp == 0) { /* same category ... compare names */ - if (g_strcasecmp (a->name.c_str(), b->name.c_str()) < 0) { + if (cmp_nocase_utf8 (a->name, b->name) < 0) { return true; } } @@ -600,12 +745,16 @@ PluginSelector::build_plugin_menu () PluginInfoList all_plugs; all_plugs.insert (all_plugs.end(), manager.ladspa_plugin_info().begin(), manager.ladspa_plugin_info().end()); + all_plugs.insert (all_plugs.end(), manager.lua_plugin_info().begin(), manager.lua_plugin_info().end()); #ifdef WINDOWS_VST_SUPPORT all_plugs.insert (all_plugs.end(), manager.windows_vst_plugin_info().begin(), manager.windows_vst_plugin_info().end()); #endif #ifdef LXVST_SUPPORT all_plugs.insert (all_plugs.end(), manager.lxvst_plugin_info().begin(), manager.lxvst_plugin_info().end()); #endif +#ifdef MACVST_SUPPORT + all_plugs.insert (all_plugs.end(), manager.mac_vst_plugin_info().begin(), manager.mac_vst_plugin_info().end()); +#endif #ifdef AUDIOUNIT_SUPPORT all_plugs.insert (all_plugs.end(), manager.au_plugin_info().begin(), manager.au_plugin_info().end()); #endif @@ -636,6 +785,34 @@ PluginSelector::build_plugin_menu () items.push_back (MenuElem (_("By Category"), *manage (by_category))); } +string +GetPluginTypeStr(PluginInfoPtr info) +{ + string type; + + switch (info->type) { + case LADSPA: + type = X_(" (LADSPA)"); + break; + case AudioUnit: + type = X_(" (AU)"); + break; + case LV2: + type = X_(" (LV2)"); + break; + case Windows_VST: + case LXVST: + case MacVST: + type = X_(" (VST)"); + break; + case Lua: + type = X_(" (Lua)"); + break; + } + + return type; +} + Gtk::Menu* PluginSelector::create_favs_menu (PluginInfoList& all_plugs) { @@ -649,7 +826,8 @@ PluginSelector::create_favs_menu (PluginInfoList& all_plugs) for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) { if (manager.get_status (*i) == PluginManager::Favorite) { - MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); + string typ = GetPluginTypeStr(*i); + MenuElem elem ((*i)->name + typ, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); elem.get_child()->set_use_underline (false); favs->items().push_back (elem); } @@ -677,11 +855,26 @@ PluginSelector::create_by_creator_menu (ARDOUR::PluginInfoList& all_plugs) if (manager.get_status (*i) == PluginManager::Hidden) continue; string creator = (*i)->creator; - - /* stupid LADSPA creator strings */ string::size_type pos = 0; - while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; - creator = creator.substr (0, pos); + + if ((*i)->type == ARDOUR::LADSPA) { + /* stupid LADSPA creator strings */ +#ifdef PLATFORM_WINDOWS + while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#else + while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]))) ++pos; +#endif + } else { + pos = creator.length (); + } + + // If there were too few characters to create a + // meaningful name, mark this creator as 'Unknown' + if (creator.length() < 2 || pos < 3) { + creator = "Unknown"; + } else{ + creator = creator.substr (0, pos); + } SubmenuMap::iterator x; Gtk::Menu* submenu; @@ -693,7 +886,8 @@ PluginSelector::create_by_creator_menu (ARDOUR::PluginInfoList& all_plugs) creator_submenu_map.insert (pair (creator, submenu)); submenu->set_name("ArdourContextMenu"); } - MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); + string typ = GetPluginTypeStr(*i); + MenuElem elem ((*i)->name+typ, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); elem.get_child()->set_use_underline (false); submenu->items().push_back (elem); } @@ -731,7 +925,8 @@ PluginSelector::create_by_category_menu (ARDOUR::PluginInfoList& all_plugs) category_submenu_map.insert (pair (category, submenu)); submenu->set_name("ArdourContextMenu"); } - MenuElem elem ((*i)->name, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); + string typ = GetPluginTypeStr(*i); + MenuElem elem ((*i)->name + typ, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))); elem.get_child()->set_use_underline (false); submenu->items().push_back (elem); } @@ -824,6 +1019,96 @@ PluginSelector::hidden_changed (const std::string& path) in_row_change = false; } +bool +PluginSelector::fil_hidden_button_release (GdkEventButton*) +{ + _show_hidden = (fil_hidden_button.active_state() == 0); + fil_hidden_button.set_active (_show_hidden); + refill (); + return false; +} + +static Gtkmm2ext::ActiveState next_state (Gtkmm2ext::ActiveState s){ + switch (s) { + case Gtkmm2ext::Off: + return Gtkmm2ext::ImplicitActive; + break; + case Gtkmm2ext::ImplicitActive: + return Gtkmm2ext::ExplicitActive; + break; + case Gtkmm2ext::ExplicitActive: + return Gtkmm2ext::Off; + break; + default: assert(0); break; // not reached + } + /* impossible, but keep some compiles happy */ + fatal << string_compose (_("programming error: %1"), + X_("Illegal Active State.")) + << endmsg; + abort(); /*NOTREACHED*/ + return Gtkmm2ext::Off; +} + +static Gtkmm2ext::ActiveState prev_state (Gtkmm2ext::ActiveState s){ + switch (s) { + case Gtkmm2ext::Off: + return Gtkmm2ext::ExplicitActive; + break; + case Gtkmm2ext::ImplicitActive: + return Gtkmm2ext::Off; + break; + case Gtkmm2ext::ExplicitActive: + return Gtkmm2ext::ImplicitActive; + break; + default: assert(0); break; // not reached + } + /* impossible, but keep some compiles happy */ + fatal << string_compose (_("programming error: %1"), + X_("Illegal Active State.")) + << endmsg; + abort(); /*NOTREACHED*/ + return Gtkmm2ext::Off; +} + +bool +PluginSelector::fil_instruments_button_release (GdkEventButton* ev) +{ + if (ev->button == 3) { + _show_instruments = prev_state (fil_instruments_button.active_state()); + } else { + _show_instruments = next_state (fil_instruments_button.active_state()); + } + fil_instruments_button.set_active_state (_show_instruments); + refill (); + return false; +} + +bool +PluginSelector::fil_analysis_button_release (GdkEventButton* ev) +{ + if (ev->button == 3) { + _show_analysers = prev_state (fil_analysis_button.active_state()); + } else { + _show_analysers = next_state (fil_analysis_button.active_state()); + } + fil_analysis_button.set_active_state (_show_analysers); + refill (); + return false; +} + +bool +PluginSelector::fil_utils_button_release (GdkEventButton* ev) +{ + if (ev->button == 3) { + _show_utils = prev_state (fil_utils_button.active_state()); + } else { + _show_utils = next_state (fil_utils_button.active_state()); + } + fil_utils_button.set_active_state (_show_utils); + refill (); + return false; +} + void PluginSelector::show_manager () {