View Issue Details

IDCategoryLast Update
0007581features2018-03-23 23:21
ReporterunfaAssigned To 
Reproducibilityhave not tried 
Status newResolutionopen 
Product Version 
Fixed in Version 
Summary0007581: Track local plugins usage statistics and present a "most used" list to pick from
DescriptionI see that after a while of me using Ardour, my "Favorite" plugin list becomes really long. I don't really want to spend the time cleaning it up, but I'll have to at some point.

I thought that it'd be really useful if Ardour kept track of how frequently I use certain plugins and allowed me to sorry my plug-in list by that frequency.

It's greatly appreciate up the prices of me finding the plugins that I use body often - without me needing to manually organize such a list.

The two could be combined - it could sorry the favorites list by usage frequency.

I know that plugin lists departing places on thru own could be frustrating, but I've think I eager more time searching through my favourites list - I'm slowly stopping to use that at all because of faster to type the name in the plugin manager search box.
TagsNo tags attached.

Activities

relascope

2018-03-23 23:00

reporter  

featurRecentPlugin.diff (6,758 bytes)
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 9796107f0..26d5e2f9f 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -796,6 +796,11 @@ PluginSelector::run ()
 				}
 			}
 			if (interested_object && !plugins.empty()) {
+				for  (vector<PluginPtr>::iterator j = plugins.begin(); j != plugins.end(); ++j) {
+					manager.add_recent((*j)->get_info());
+				}
+
+				_need_menu_rebuild = true;
 				finish = !interested_object->use_plugins (plugins);
 			}
 
@@ -1003,6 +1008,10 @@ PluginSelector::build_plugin_menu ()
 	items.push_back (MenuElem (_("Favorites"), *manage (favs)));
 
 	items.push_back (MenuElem (_("Plugin Manager..."), sigc::mem_fun (*this, &PluginSelector::show_manager)));
+
+	Gtk::Menu* recent = create_recent_menu(all_plugs);
+	items.push_back (MenuElem (_("Recent"), *manage (recent)));
+
 	items.push_back (SeparatorElem ());
 
 	Menu* by_creator = create_by_creator_menu(all_plugs);
@@ -1062,6 +1071,30 @@ PluginSelector::create_favs_menu (PluginInfoList& all_plugs)
 	return favs;
 }
 
+Gtk::Menu*
+PluginSelector::create_recent_menu(PluginInfoList& all_plugs)
+{
+	using namespace Menu_Helpers;
+
+	Menu* recents = new Menu();
+	recents->set_name("ArdourContextMenu");
+
+	PluginManager::RecentPluginList recent_plugs = manager.get_recents();
+
+	// plugins are sorted alphabetically to keep conformity with the Recent Session window
+	PluginMenuCompareByName cmp_by_name;
+	all_plugs.sort(cmp_by_name);
+	for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
+		if (std::find(recent_plugs.begin(), recent_plugs.end(), (*i)->unique_id) != recent_plugs.end()) {
+			string type = GetPluginTypeStr(*i);
+			MenuElem elem ((*i)->name + type, (sigc::bind (sigc::mem_fun (*this, &PluginSelector::plugin_chosen_from_menu), *i)));
+			elem.get_child()->set_use_underline (false);
+			recents->items().push_back (elem);
+		}
+	}
+	return recents;
+}
+
 Gtk::Menu*
 PluginSelector::create_by_creator_menu (ARDOUR::PluginInfoList& all_plugs)
 {
@@ -1170,6 +1203,8 @@ PluginSelector::plugin_chosen_from_menu (const PluginInfoPtr& pi)
 	if (p && interested_object) {
 		SelectedPlugins plugins;
 		plugins.push_back (p);
+		manager.add_recent(pi);
+		manager.PluginListChanged();
 		interested_object->use_plugins (plugins);
 	}
 
diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h
index bba22950b..2dff879c2 100644
--- a/gtk2_ardour/plugin_selector.h
+++ b/gtk2_ardour/plugin_selector.h
@@ -180,6 +180,7 @@ private:
 	void plugin_status_changed ( ARDOUR::PluginType t, std::string unique_id, ARDOUR::PluginManager::PluginStatusType s );
 
 	Gtk::Menu* create_favs_menu (ARDOUR::PluginInfoList&);
+	Gtk::Menu* create_recent_menu (ARDOUR::PluginInfoList&);
 	Gtk::Menu* create_by_creator_menu (ARDOUR::PluginInfoList&);
 	Gtk::Menu* create_by_tags_menu (ARDOUR::PluginInfoList&);
 	void build_plugin_menu ();
diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h
index a66e2d067..254d5f5de 100644
--- a/libs/ardour/ardour/plugin_manager.h
+++ b/libs/ardour/ardour/plugin_manager.h
@@ -24,6 +24,7 @@
 #include "libardour-config.h"
 #endif
 
+#include <deque>
 #include <list>
 #include <map>
 #include <string>
@@ -82,6 +83,11 @@ public:
 	void set_status (ARDOUR::PluginType type, std::string unique_id, PluginStatusType status);
 	PluginStatusType get_status (const PluginInfoPtr&) const;
 
+	typedef std::deque<std::string> RecentPluginList;
+
+	const RecentPluginList get_recents() const;
+	void add_recent(const PluginInfoPtr&);
+
 	void load_tags ();
 	void save_tags ();
 
@@ -167,6 +173,11 @@ private:
 	typedef std::set<PluginStatus> PluginStatusList;
 	PluginStatusList statuses;
 
+	void load_recents ();
+	void save_recents ();
+
+	RecentPluginList recents;
+
 	ARDOUR::PluginInfoList  _empty_plugin_info;
 	ARDOUR::PluginInfoList* _windows_vst_plugin_info;
 	ARDOUR::PluginInfoList*	_lxvst_plugin_info;
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 681c51a32..839467891 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -246,6 +246,7 @@ CONFIG_VARIABLE (int, vst_scan_timeout, "vst-scan-timeout", 1200) /* deciseconds
 CONFIG_VARIABLE (bool, discover_audio_units, "discover-audio-units", false)
 CONFIG_VARIABLE (bool, ask_replace_instrument, "ask-replace-instrument", true)
 CONFIG_VARIABLE (bool, ask_setup_instrument, "ask-setup-instrument", true)
+CONFIG_VARIABLE (uint32_t, max_recent_plugins, "max-recent-plugins", 10)
 
 /* custom user plugin paths */
 CONFIG_VARIABLE (std::string, plugin_path_vst, "plugin-path-vst", "@default@")
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 233f986a7..f42f821ec 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -176,6 +176,8 @@ PluginManager::PluginManager ()
 
 	load_tags ();
 
+	load_recents();
+
 	if ((s = getenv ("LADSPA_RDF_PATH"))){
 		lrdf_path = s;
 	}
@@ -1478,6 +1480,74 @@ PluginManager::set_status (PluginType t, string id, PluginStatusType status)
 	PluginStatusChanged (t, id, status); /* EMIT SIGNAL */
 }
 
+void
+PluginManager::load_recents()
+{
+	recents.clear();
+
+	std::string path;
+	find_file (plugin_metadata_search_path(), "plugin_recent", path);  //note: if no user folder is found, this will find the resources path
+	gchar *fbuf = NULL;
+	if (!g_file_get_contents (path.c_str(), &fbuf, NULL, NULL))  {
+		return;
+	}
+	stringstream ifs (fbuf);
+	g_free (fbuf);
+
+	std::string id;
+	char buf[1024];
+
+	while (ifs) {
+		ifs.getline (buf, sizeof (buf), '\n');
+		if (!ifs) {
+			break;
+		}
+
+		id = buf;
+		strip_whitespace_edges (id);
+
+		recents.push_back(id);
+	}
+}
+
+void
+PluginManager::save_recents()
+{
+	std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_recent");
+	stringstream ofs;
+
+	for (RecentPluginList::iterator i = recents.begin(); i != recents.end(); ++i) {
+		ofs << *i;
+		ofs << endl;
+	}
+	g_file_set_contents (path.c_str(), ofs.str().c_str(), -1, NULL);
+}
+
+void
+PluginManager::add_recent(const PluginInfoPtr & piptr)
+{
+	load_recents();
+
+	std::remove(recents.begin(), recents.end(), piptr->unique_id);
+
+	recents.push_front(piptr->unique_id);
+
+	// TODO ConfigValue
+	uint32_t max_recent_sessions = Config->get_max_recent_plugins();
+
+	if (recents.size() > max_recent_sessions) {
+		recents.erase(recents.begin()+max_recent_sessions, recents.end());
+	}
+
+	save_recents();
+}
+
+const PluginManager::RecentPluginList
+PluginManager::get_recents() const
+{
+	return recents;
+}
+
 PluginType
 PluginManager::to_generic_vst (const PluginType t)
 {
featurRecentPlugin.diff (6,758 bytes)

relascope

2018-03-23 23:21

reporter   ~0020216

Attached an implementation (git diff) of the feature.



Implementation details:

Plugins sorted alphabetically to keep integrity with Recent-Session view. (stored per usage in the model).

New Configuration variable max-recent-plugins.

Issue History

Date Modified Username Field Change
2018-03-01 16:45 unfa New Issue
2018-03-23 23:00 relascope File Added: featurRecentPlugin.diff
2018-03-23 23:21 relascope Note Added: 0020216