Small cleanups to port matrix context menu.
[ardour.git] / gtk2_ardour / plugin_selector.cc
index b49d6a0b7702b769606defc5e8428be9a205e05e..c2f81f4981b10d3ad8b28da51faf5dcd88b5d757 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2006 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -16,6 +16,9 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 */
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#endif
 
 #include <cstdio>
 #include <lrdf.h>
 
 #include <gtkmm2ext/utils.h>
 
-#include <pbd/convert.h>
+#include "pbd/convert.h"
 
-#include <ardour/plugin_manager.h>
-#include <ardour/plugin.h>
-#include <ardour/configuration.h>
+#include "ardour/plugin_manager.h"
+#include "ardour/plugin.h"
+#include "ardour/configuration.h"
+#include "ardour/session.h"
 
 #include "ardour_ui.h"
 #include "plugin_selector.h"
@@ -50,9 +54,11 @@ using namespace std;
 static const char* _filter_mode_strings[] = {
        N_("Name contains"),
        N_("Type contains"),
+       N_("Category contains"),
        N_("Author contains"),
        N_("Library contains"),
        N_("Favorites only"),
+       N_("Hidden only"),
        0
 };
 
@@ -72,9 +78,11 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        plugin_model = Gtk::ListStore::create (plugin_columns);
        plugin_display.set_model (plugin_model);
        /* XXX translators: try to convert "Fav" into a short term
-          related to "favorite"
+          related to "favorite" and "Hid" into a short term
+          related to "hidden"
        */
        plugin_display.append_column (_("Fav"), plugin_columns.favorite);
+       plugin_display.append_column (_("Hid"), plugin_columns.hidden);
        plugin_display.append_column (_("Available Plugins"), plugin_columns.name);
        plugin_display.append_column (_("Type"), plugin_columns.type_name);
        plugin_display.append_column (_("Category"), plugin_columns.category);
@@ -90,9 +98,14 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        CellRendererToggle* fav_cell = dynamic_cast<CellRendererToggle*>(plugin_display.get_column_cell_renderer (0));
        fav_cell->property_activatable() = true;
-       fav_cell->property_radio() = false;
+       fav_cell->property_radio() = true;
        fav_cell->signal_toggled().connect (mem_fun (*this, &PluginSelector::favorite_changed));
 
+       CellRendererToggle* hidden_cell = dynamic_cast<CellRendererToggle*>(plugin_display.get_column_cell_renderer (1));
+       hidden_cell->property_activatable() = true;
+       hidden_cell->property_radio() = true;
+       hidden_cell->signal_toggled().connect (mem_fun (*this, &PluginSelector::hidden_changed));
+
        scroller.set_border_width(10);
        scroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        scroller.add(plugin_display);
@@ -103,7 +116,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        added_list.set_headers_visible (true);
        added_list.set_reorderable (false);
 
-       for (int i = 0; i <=7; i++) {
+       for (int i = 0; i <=8; i++) {
                Gtk::TreeView::Column* column = plugin_display.get_column(i);
                column->set_sort_column(i);
        }
@@ -148,13 +161,13 @@ PluginSelector::PluginSelector (PluginManager *mgr)
 
        table->attach (*filter_box, 0, 7, 5, 6, FILL|EXPAND, FILL, 5, 5);
 
-       table->attach(*btn_add, 1, 2, 6, 7, FILL, FILL, 5, 5); 
+       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);
 
        table->attach(ascroller, 0, 7, 8, 10);
 
-       add_button (Stock::CANCEL, RESPONSE_CANCEL);
+       add_button (Stock::CLOSE, RESPONSE_CLOSE);
        add_button (_("Insert Plugin(s)"), RESPONSE_APPLY);
        set_default_response (RESPONSE_APPLY);
        set_response_sensitive (RESPONSE_APPLY, false);
@@ -168,7 +181,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        plugin_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
        plugin_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::display_selection_changed));
        plugin_display.grab_focus();
-       
+
        btn_update->signal_clicked().connect (mem_fun(*this, &PluginSelector::btn_update_clicked));
        btn_add->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_add_clicked));
        btn_remove->signal_clicked().connect(mem_fun(*this, &PluginSelector::btn_remove_clicked));
@@ -188,7 +201,7 @@ void
 PluginSelector::set_session (Session* s)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &PluginSelector::set_session), s));
-       
+
        session = s;
 
        if (session) {
@@ -203,20 +216,45 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string&
        std::string mode = filter_mode.get_active_text ();
 
        if (mode == _("Favorites only")) {
-               return manager->is_a_favorite_plugin (info);
+               return manager->get_status (info) == PluginManager::Favorite;
+       }
+
+       if (mode == _("Hidden only")) {
+               return manager->get_status (info) == PluginManager::Hidden;
        }
 
        if (!filterstr.empty()) {
-               
+
                if (mode == _("Name contains")) {
                        compstr = info->name;
-               } else if (mode == _("Type contains")) {
+               } else if (mode == _("Category contains")) {
                        compstr = info->category;
+               } else if (mode == _("Type contains")) {
+
+                       switch (info->type) {
+                       case LADSPA:
+                               compstr = X_("LADSPA");
+                               break;
+                       case AudioUnit:
+                               compstr = X_("AudioUnit");
+                               break;
+                       case LV2:
+                               compstr = X_("LV2");
+                               break;
+                       case VST:
+                               compstr = X_("VST");
+                               break;
+                       }
+
                } else if (mode == _("Author contains")) {
                        compstr = info->creator;
                } else if (mode == _("Library contains")) {
                        compstr = info->path;
-               } 
+               }
+
+               if (compstr.empty()) {
+                       return false;
+               }
 
                transform (compstr.begin(), compstr.end(), compstr.begin(), ::toupper);
 
@@ -235,7 +273,7 @@ PluginSelector::setup_filter_string (string& filterstr)
 {
        filterstr = filter_entry.get_text ();
        transform (filterstr.begin(), filterstr.end(), filterstr.begin(), ::toupper);
-}      
+}
 
 void
 PluginSelector::refill ()
@@ -266,7 +304,8 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte
                if (show_this_plugin (*i, filterstr)) {
 
                        TreeModel::Row newrow = *(plugin_model->append());
-                       newrow[plugin_columns.favorite] = manager->is_a_favorite_plugin (*i);
+                       newrow[plugin_columns.favorite] = (manager->get_status (*i) == PluginManager::Favorite);
+                       newrow[plugin_columns.hidden] = (manager->get_status (*i) == PluginManager::Hidden);
                        newrow[plugin_columns.name] = (*i)->name;
                        newrow[plugin_columns.type_name] = type;
                        newrow[plugin_columns.category] = (*i)->category;
@@ -281,28 +320,19 @@ PluginSelector::refiller (const PluginInfoList& plugs, const::std::string& filte
 
                        newrow[plugin_columns.creator] = creator;
 
-                       if ((*i)->n_inputs.n_total() < 0) {
-                               newrow[plugin_columns.audio_ins] = "various";
-                               newrow[plugin_columns.midi_ins] = "various";
-                       } else {
-                               snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_audio());
-                               newrow[plugin_columns.audio_ins] = buf;
-                               snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi());
-                               newrow[plugin_columns.midi_ins] = buf;
-                       }
-                       if ((*i)->n_outputs.n_total() < 0) {
-                               newrow[plugin_columns.audio_outs] = "various";
-                               newrow[plugin_columns.midi_outs] = "various";
-                       } else {
-                               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());            
-                               newrow[plugin_columns.midi_outs] = buf;
-                       }
+                       snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_audio());
+                       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());
+                       newrow[plugin_columns.midi_outs] = buf;
 
                        newrow[plugin_columns.plugin] = *i;
                }
-       }       
+       }
 }
 
 void
@@ -314,13 +344,17 @@ PluginSelector::ladspa_refiller (const std::string& filterstr)
 void
 PluginSelector::lv2_refiller (const std::string& filterstr)
 {
-#ifdef HAVE_LV2
+#ifdef HAVE_SLV2
        refiller (manager->lv2_plugin_info(), filterstr, "LV2");
 #endif
 }
 
 void
+#ifdef VST_SUPPORT
 PluginSelector::vst_refiller (const std::string& filterstr)
+#else
+PluginSelector::vst_refiller (const std::string&)
+#endif
 {
 #ifdef VST_SUPPORT
        refiller (manager->vst_plugin_info(), filterstr, "VST");
@@ -328,7 +362,11 @@ PluginSelector::vst_refiller (const std::string& filterstr)
 }
 
 void
+#ifdef HAVE_AUDIOUNITS
 PluginSelector::au_refiller (const std::string& filterstr)
+#else
+PluginSelector::au_refiller (const std::string&)
+#endif
 {
 #ifdef HAVE_AUDIOUNITS
        refiller (manager->au_plugin_info(), filterstr, "AU");
@@ -369,7 +407,7 @@ void
 PluginSelector::btn_remove_clicked()
 {
        TreeModel::iterator iter = added_list.get_selection()->get_selected();
-       
+
        amodel->erase(iter);
        if (amodel->children().empty()) {
                set_response_sensitive (RESPONSE_APPLY, false);
@@ -424,7 +462,7 @@ PluginSelector::run ()
                if (interested_object && !plugins.empty()) {
                        interested_object->use_plugins (plugins);
                }
-               
+
                break;
 
        default:
@@ -450,12 +488,12 @@ PluginSelector::filter_entry_changed ()
        refill ();
 }
 
-void 
+void
 PluginSelector::filter_mode_changed ()
 {
        std::string mode = filter_mode.get_active_text ();
 
-       if (mode == _("Favorites only")) {
+       if (mode == _("Favorites only") || mode == _("Hidden only")) {
                filter_entry.set_sensitive (false);
        } else {
                filter_entry.set_sensitive (true);
@@ -471,7 +509,7 @@ PluginSelector::on_show ()
        filter_entry.grab_focus ();
 }
 
-struct PluginMenuCompare {
+struct PluginMenuCompareByCreator {
     bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
            int cmp;
 
@@ -483,34 +521,51 @@ struct PluginMenuCompare {
                    /* same creator ... compare names */
                    if (strcasecmp (a->name.c_str(), b->name.c_str()) < 0) {
                            return true;
-                   } 
+                   }
            }
            return false;
     }
 };
 
-Gtk::Menu&
-PluginSelector::plugin_menu()
-{
-       using namespace Menu_Helpers;
+struct PluginMenuCompareByName {
+    bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
+           int cmp;
 
-       typedef std::map<Glib::ustring,Gtk::Menu*> SubmenuMap;
-       SubmenuMap submenu_map;
+           cmp = strcasecmp (a->name.c_str(), b->name.c_str());
 
-       if (!_menu) {
-               _menu = new Menu();
-               _menu->set_name("ArdourContextMenu");
-       } 
+           if (cmp < 0) {
+                   return true;
+           } else if (cmp == 0) {
+                   /* same name ... compare type */
+                   if (a->type < b->type) {
+                           return true;
+                   }
+           }
+           return false;
+    }
+};
 
-       MenuList& items = _menu->items();
-       Menu* favs = new Menu();
-       favs->set_name("ArdourContextMenu");
+struct PluginMenuCompareByCategory {
+    bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
+           int cmp;
 
-       items.clear ();
-       items.push_back (MenuElem (_("Favorites"), *favs));
-       items.push_back (MenuElem (_("Plugin Manager"), mem_fun (*this, &PluginSelector::show_manager)));
-       items.push_back (SeparatorElem ());
+           cmp = strcasecmp (a->category.c_str(), b->category.c_str());
+
+           if (cmp < 0) {
+                   return true;
+           } else if (cmp == 0) {
+                   /* same category ... compare names */
+                   if (strcasecmp (a->name.c_str(), b->name.c_str()) < 0) {
+                           return true;
+                   }
+           }
+           return false;
+    }
+};
 
+Gtk::Menu&
+PluginSelector::plugin_menu()
+{
        PluginInfoList all_plugs;
 
        all_plugs.insert (all_plugs.end(), manager->ladspa_plugin_info().begin(), manager->ladspa_plugin_info().end());
@@ -520,42 +575,129 @@ PluginSelector::plugin_menu()
 #ifdef HAVE_AUDIOUNITS
        all_plugs.insert (all_plugs.end(), manager->au_plugin_info().begin(), manager->au_plugin_info().end());
 #endif
-#ifdef HAVE_LV2
+#ifdef HAVE_SLV2
        all_plugs.insert (all_plugs.end(), manager->lv2_plugin_info().begin(), manager->lv2_plugin_info().end());
 #endif
 
-       PluginMenuCompare cmp;
-       all_plugs.sort (cmp);
+       using namespace Menu_Helpers;
 
-       for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
-               SubmenuMap::iterator x;
-               Gtk::Menu* submenu;
+       if (!_menu) {
+               _menu = new Menu();
+               _menu->set_name("ArdourContextMenu");
+       }
 
-               string creator = (*i)->creator;
-               string::size_type pos = 0;
+       MenuList& items = _menu->items();
+       items.clear ();
+
+       Gtk::Menu* favs = create_favs_menu(all_plugs);
+       items.push_back (MenuElem (_("Favorites"), *favs));
+
+       items.push_back (MenuElem (_("Plugin Manager"), mem_fun (*this, &PluginSelector::show_manager)));
+       items.push_back (SeparatorElem ());
+
+       Menu* by_creator = create_by_creator_menu(all_plugs);
+       items.push_back (MenuElem (_("By Creator"), *by_creator));
 
-               if (manager->is_a_favorite_plugin (*i)) {
+       Menu* by_category = create_by_category_menu(all_plugs);
+       items.push_back (MenuElem (_("By Category"), *by_category));
+
+       return *_menu;
+}
+
+Gtk::Menu*
+PluginSelector::create_favs_menu (PluginInfoList& all_plugs)
+{
+       using namespace Menu_Helpers;
+
+       Menu* favs = new Menu();
+       favs->set_name("ArdourContextMenu");
+
+       PluginMenuCompareByName cmp_by_name;
+       all_plugs.sort (cmp_by_name);
+
+       for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
+               if (manager->get_status (*i) == PluginManager::Favorite) {
                        favs->items().push_back (MenuElem ((*i)->name, (bind (mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))));
                }
-               
+       }
+       return favs;
+}
+
+Gtk::Menu*
+PluginSelector::create_by_creator_menu (ARDOUR::PluginInfoList& all_plugs)
+{
+       using namespace Menu_Helpers;
+
+       typedef std::map<Glib::ustring,Gtk::Menu*> SubmenuMap;
+       SubmenuMap creator_submenu_map;
+
+       Menu* by_creator = new Menu();
+       by_creator->set_name("ArdourContextMenu");
+
+       MenuList& by_creator_items = by_creator->items();
+       PluginMenuCompareByCreator cmp_by_creator;
+       all_plugs.sort (cmp_by_creator);
+
+       for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
+
+               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 ((x = submenu_map.find (creator)) != submenu_map.end()) {
+               SubmenuMap::iterator x;
+               Gtk::Menu* submenu;
+               if ((x = creator_submenu_map.find (creator)) != creator_submenu_map.end()) {
                        submenu = x->second;
                } else {
                        submenu = new Gtk::Menu;
-                       items.push_back (MenuElem (creator, *submenu));
-                       submenu_map.insert (pair<Glib::ustring,Menu*> (creator, submenu));
+                       by_creator_items.push_back (MenuElem (creator, *submenu));
+                       creator_submenu_map.insert (pair<Glib::ustring,Menu*> (creator, submenu));
                        submenu->set_name("ArdourContextMenu");
                }
-               
                submenu->items().push_back (MenuElem ((*i)->name, (bind (mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))));
        }
-       
-       return *_menu;
+       return by_creator;
+}
+
+Gtk::Menu*
+PluginSelector::create_by_category_menu (ARDOUR::PluginInfoList& all_plugs)
+{
+       using namespace Menu_Helpers;
+
+       typedef std::map<Glib::ustring,Gtk::Menu*> SubmenuMap;
+       SubmenuMap category_submenu_map;
+
+       Menu* by_category = new Menu();
+       by_category->set_name("ArdourContextMenu");
+
+       MenuList& by_category_items = by_category->items();
+       PluginMenuCompareByCategory cmp_by_category;
+       all_plugs.sort (cmp_by_category);
+
+       for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
+
+               if (manager->get_status (*i) == PluginManager::Hidden) continue;
+
+               string category = (*i)->category;
+
+               SubmenuMap::iterator x;
+               Gtk::Menu* submenu;
+               if ((x = category_submenu_map.find (category)) != category_submenu_map.end()) {
+                       submenu = x->second;
+               } else {
+                       submenu = new Gtk::Menu;
+                       by_category_items.push_back (MenuElem (category, *submenu));
+                       category_submenu_map.insert (pair<Glib::ustring,Menu*> (category, submenu));
+                       submenu->set_name("ArdourContextMenu");
+               }
+               submenu->items().push_back (MenuElem ((*i)->name, (bind (mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i))));
+       }
+       return by_category;
 }
 
 void
@@ -572,7 +714,7 @@ PluginSelector::plugin_chosen_from_menu (const PluginInfoPtr& pi)
        interested_object = 0;
 }
 
-void 
+void
 PluginSelector::favorite_changed (const Glib::ustring& path)
 {
        PluginInfoPtr pi;
@@ -582,9 +724,9 @@ PluginSelector::favorite_changed (const Glib::ustring& path)
        }
 
        in_row_change = true;
-       
+
        TreeModel::iterator iter = plugin_model->get_iter (path);
-       
+
        if (iter) {
 
                bool favorite = !(*iter)[plugin_columns.favorite];
@@ -592,18 +734,50 @@ PluginSelector::favorite_changed (const Glib::ustring& path)
                /* change state */
 
                (*iter)[plugin_columns.favorite] = favorite;
+               (*iter)[plugin_columns.hidden] = false;
+               PluginManager::PluginStatusType status = (favorite ? PluginManager::Favorite : PluginManager::Normal);
 
-               /* save new favorites list */
+               /* save new statuses list */
 
                pi = (*iter)[plugin_columns.plugin];
-               
-               if (favorite) {
-                       manager->add_favorite (pi->type, pi->unique_id);
-               } else {
-                       manager->remove_favorite (pi->type, pi->unique_id);
-               }
-               
-               manager->save_favorites ();
+
+               manager->set_status (pi->type, pi->unique_id, status);
+
+               manager->save_statuses ();
+       }
+       in_row_change = false;
+}
+
+void
+PluginSelector::hidden_changed (const Glib::ustring& path)
+{
+       PluginInfoPtr pi;
+
+       if (in_row_change) {
+               return;
+       }
+
+       in_row_change = true;
+
+       TreeModel::iterator iter = plugin_model->get_iter (path);
+
+       if (iter) {
+
+               bool hidden = !(*iter)[plugin_columns.hidden];
+
+               /* change state */
+
+               (*iter)[plugin_columns.favorite] = false;
+               (*iter)[plugin_columns.hidden] = hidden;
+               PluginManager::PluginStatusType status = (hidden ? PluginManager::Hidden : PluginManager::Normal);
+
+               /* save new statuses list */
+
+               pi = (*iter)[plugin_columns.plugin];
+
+               manager->set_status (pi->type, pi->unique_id, status);
+
+               manager->save_statuses ();
        }
        in_row_change = false;
 }