#include <cstring>
#endif //LXVST_SUPPORT
+#ifdef MACVST_SUPPORT
+#include "ardour/vst_info_file.h"
+#include "ardour/mac_vst_support.h"
+#include "ardour/mac_vst_plugin.h"
+#include "pbd/basename.h"
+#include "pbd/pathexpand.h"
+#include <cstring>
+#endif //MACVST_SUPPORT
+
#include <glibmm/miscutils.h>
#include <glibmm/pattern.h>
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
-#include "pbd/whitespace.h"
+#include "pbd/convert.h"
#include "pbd/file_utils.h"
+#include "pbd/tokenizer.h"
+#include "pbd/whitespace.h"
+#include "ardour/directory_names.h"
#include "ardour/debug.h"
#include "ardour/filesystem_paths.h"
#include "ardour/ladspa.h"
#include "ardour/ladspa_plugin.h"
+#include "ardour/luascripting.h"
+#include "ardour/luaproc.h"
#include "ardour/plugin.h"
#include "ardour/plugin_manager.h"
#include "ardour/rc_configuration.h"
#include "pbd/error.h"
#include "pbd/stl_delete.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
#include "ardour/debug.h"
PluginManager::PluginManager ()
: _windows_vst_plugin_info(0)
, _lxvst_plugin_info(0)
+ , _mac_vst_plugin_info(0)
, _ladspa_plugin_info(0)
, _lv2_plugin_info(0)
, _au_plugin_info(0)
+ , _lua_plugin_info(0)
, _cancel_scan(false)
, _cancel_timeout(false)
{
char* s;
string lrdf_path;
-#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
+#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
// source-tree (ardev, etc)
PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
load_statuses ();
+ load_tags ();
+
if ((s = getenv ("LADSPA_RDF_PATH"))){
lrdf_path = s;
}
}
#endif /* Native LinuxVST support*/
+#ifdef MACVST_SUPPORT
+ if (Config->get_use_macvst ()) {
+ add_mac_vst_presets ();
+ }
+#endif
+
if ((s = getenv ("VST_PATH"))) {
windows_vst_path = s;
} else if ((s = getenv ("VST_PLUGINS"))) {
}
BootMessage (_("Discovering Plugins"));
+
+ LuaScripting::instance().scripts_changed.connect_same_thread (lua_refresh_connection, boost::bind (&PluginManager::lua_refresh_cb, this));
}
// don't bother, just exit quickly.
delete _windows_vst_plugin_info;
delete _lxvst_plugin_info;
+ delete _mac_vst_plugin_info;
delete _ladspa_plugin_info;
delete _lv2_plugin_info;
delete _au_plugin_info;
+ delete _lua_plugin_info;
}
}
BootMessage (_("Scanning LADSPA Plugins"));
ladspa_refresh ();
+ BootMessage (_("Scanning Lua DSP Processors"));
+ lua_refresh ();
#ifdef LV2_SUPPORT
BootMessage (_("Scanning LV2 Plugins"));
lv2_refresh ();
}
#endif //Native linuxVST SUPPORT
-#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
+#ifdef MACVST_SUPPORT
+ if(Config->get_use_macvst ()) {
+ if (cache_only) {
+ BootMessage (_("Scanning Mac VST Plugins"));
+ } else {
+ BootMessage (_("Discovering Mac VST Plugins"));
+ }
+ mac_vst_refresh (cache_only);
+ } else if (_mac_vst_plugin_info) {
+ _mac_vst_plugin_info->clear ();
+ } else {
+ _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
+ }
+#endif //Native Mac VST SUPPORT
+
+#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
if (!cache_only) {
string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
#endif
#endif // old cache cleanup
-#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
+#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
{
string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
vector<string> fsi_files;
#endif // old blacklist cleanup
-#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
+#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
{
string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
PluginManager::clear_au_cache ()
{
#ifdef AUDIOUNIT_SUPPORT
- // AUPluginInfo::au_cache_path ()
- string fn = Glib::build_filename (ARDOUR::user_config_directory(), "au_cache");
- if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
- ::g_unlink(fn.c_str());
- }
+ AUPluginInfo::clear_cache ();
#endif
}
#endif
}
+void
+PluginManager::lua_refresh ()
+{
+ if (_lua_plugin_info) {
+ _lua_plugin_info->clear ();
+ } else {
+ _lua_plugin_info = new ARDOUR::PluginInfoList ();
+ }
+ ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
+ for (LuaScriptList::const_iterator s = _scripts.begin(); s != _scripts.end(); ++s) {
+ LuaPluginInfoPtr lpi (new LuaPluginInfo(*s));
+ _lua_plugin_info->push_back (lpi);
+ set_tags (lpi->type, lpi->unique_id, lpi->category, true);
+ }
+}
+
+void
+PluginManager::lua_refresh_cb ()
+{
+ Glib::Threads::Mutex::Lock lm (_lock, Glib::Threads::TRY_LOCK);
+ if (!lm.locked()) {
+ return;
+ }
+ lua_refresh ();
+ PluginListChanged (); /* EMIT SIGNAL */
+}
+
void
PluginManager::ladspa_refresh ()
{
add_presets ("windows-vst");
}
+void
+PluginManager::add_mac_vst_presets()
+{
+ add_presets ("mac-vst");
+}
+
void
PluginManager::add_lxvst_presets()
{
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
for (uint32_t i = 0; ; ++i) {
+ /* if a ladspa plugin allocates memory here
+ * it is never free()ed (or plugin-dependent only when unloading).
+ * For some plugins memory allocated is incremental, we should
+ * avoid re-scanning plugins and file bug reports.
+ */
if ((descriptor = dfunc (i)) == 0) {
break;
}
PluginInfoPtr info(new LadspaPluginInfo);
info->name = descriptor->Name;
info->category = get_ladspa_category(descriptor->UniqueID);
- info->creator = descriptor->Maker;
info->path = path;
info->index = i;
info->n_inputs = ChanCount();
info->n_outputs = ChanCount();
info->type = ARDOUR::LADSPA;
+ string::size_type pos = 0;
+ string creator = descriptor->Maker;
+ /* stupid LADSPA creator strings */
+#ifdef PLATFORM_WINDOWS
+ while (pos < creator.length() && creator[pos] > -2 && creator[pos] < 256 && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
+#else
+ while (pos < creator.length() && (isalnum (creator[pos]) || isspace (creator[pos]) || creator[pos] == '.')) ++pos;
+#endif
+
+ /* If there were too few characters to create a
+ * meaningful name, mark this creator as 'Unknown'
+ */
+ if (creator.length() < 2 || pos < 3) {
+ info->creator = "Unknown";
+ } else{
+ info->creator = creator.substr (0, pos);
+ }
+
char buf[32];
snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
info->unique_id = buf;
for (uint32_t n=0; n < descriptor->PortCount; ++n) {
- if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
- if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
+ if (LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n])) {
+ if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n])) {
info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
}
- else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
+ else if (LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n])) {
info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
}
}
DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
delete _lv2_plugin_info;
_lv2_plugin_info = LV2PluginInfo::discover();
+
+ for (PluginInfoList::iterator i = _lv2_plugin_info->begin(); i != _lv2_plugin_info->end(); ++i) {
+ set_tags ((*i)->type, (*i)->unique_id, (*i)->category, true);
+ }
}
#endif
// successful scan re-enabled automatic discovery if it was set
Config->set_discover_audio_units (discover_at_start);
Config->save_state();
+
+ for (PluginInfoList::iterator i = _au_plugin_info->begin(); i != _au_plugin_info->end(); ++i) {
+ set_tags ((*i)->type, (*i)->unique_id, (*i)->category, true);
+ }
}
#endif
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering Windows VST plugins along %1\n", path));
+ if (Session::get_disable_all_loaded_plugins ()) {
+ info << _("Disabled WindowsVST scan (safe mode)") << endmsg;
+ return -1;
+ }
+
if (Config->get_verbose_plugin_scan()) {
info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
}
- find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
+ find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
info->unique_id = buf;
- info->category = "VST";
+ info->category = finfo->Category;
info->path = path;
info->creator = finfo->creator;
info->index = 0;
info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
info->type = ARDOUR::Windows_VST;
+ /* if we don't have any tags for this plugin, make some up. */
+ set_tags (info->type, info->unique_id, info->category, true);
+
// TODO: check dup-IDs (lxvst AND windows vst)
bool duplicate = false;
#endif // WINDOWS_VST_SUPPORT
+#ifdef MACVST_SUPPORT
+void
+PluginManager::mac_vst_refresh (bool cache_only)
+{
+ if (_mac_vst_plugin_info) {
+ _mac_vst_plugin_info->clear ();
+ } else {
+ _mac_vst_plugin_info = new ARDOUR::PluginInfoList();
+ }
+
+ mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
+}
+
+static bool mac_vst_filter (const string& str)
+{
+ string plist = Glib::build_filename (str, "Contents", "Info.plist");
+ if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
+ return false;
+ }
+ return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
+}
+
+int
+PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
+{
+ if (Session::get_disable_all_loaded_plugins ()) {
+ info << _("Disabled MacVST scan (safe mode)") << endmsg;
+ return -1;
+ }
+
+ Searchpath paths (path);
+ /* customized version of run_functor_for_paths() */
+ for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+ string expanded_path = path_expand (*i);
+ if (!Glib::file_test (expanded_path, Glib::FILE_TEST_IS_DIR)) continue;
+ try {
+ Glib::Dir dir(expanded_path);
+ for (Glib::DirIterator di = dir.begin(); di != dir.end(); di++) {
+ string fullpath = Glib::build_filename (expanded_path, *di);
+
+ /* we're only interested in bundles */
+ if (!Glib::file_test (fullpath, Glib::FILE_TEST_IS_DIR)) {
+ continue;
+ }
+
+ if (mac_vst_filter (fullpath)) {
+ ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled());
+ mac_vst_discover (fullpath, cache_only || cancelled());
+ continue;
+ }
+
+ /* don't descend into AU bundles in the VST dir */
+ if (fullpath[0] == '.' || (fullpath.length() > 10 && strings_equal_ignore_case (".component", fullpath.substr(fullpath.length() - 10)))) {
+ continue;
+ }
+
+ /* recurse */
+ mac_vst_discover_from_path (fullpath, cache_only);
+ }
+ } catch (Glib::FileError& err) { }
+ }
+
+ return 0;
+}
+
+int
+PluginManager::mac_vst_discover (string path, bool cache_only)
+{
+ DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
+
+ _cancel_timeout = false;
+
+ vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
+ cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
+
+ if (finfos->empty()) {
+ DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
+ return -1;
+ }
+
+ uint32_t discovered = 0;
+ for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
+ VSTInfo* finfo = *x;
+ char buf[32];
+
+ if (!finfo->canProcessReplacing) {
+ warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
+ finfo->name, PROGRAM_NAME)
+ << endl;
+ continue;
+ }
+
+ PluginInfoPtr info (new MacVSTPluginInfo);
+
+ info->name = finfo->name;
+
+ snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
+ info->unique_id = buf;
+ info->category = finfo->Category;
+ info->path = path;
+ info->creator = finfo->creator;
+ info->index = 0;
+ info->n_inputs.set_audio (finfo->numInputs);
+ info->n_outputs.set_audio (finfo->numOutputs);
+ info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
+ info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
+ info->type = ARDOUR::MacVST;
+
+ /* if we don't have any tags for this plugin, make some up. */
+ set_tags (info->type, info->unique_id, info->category, true);
+
+ bool duplicate = false;
+ if (!_mac_vst_plugin_info->empty()) {
+ for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
+ if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
+ warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
+ duplicate = true;
+ break;
+ }
+ }
+ }
+
+ if (!duplicate) {
+ _mac_vst_plugin_info->push_back (info);
+ discovered++;
+ }
+ }
+
+ vstfx_free_info_list (finfos);
+ return discovered > 0 ? 0 : -1;
+}
+
+#endif // MAC_VST_SUPPORT
+
#ifdef LXVST_SUPPORT
void
vector<string>::iterator x;
int ret = 0;
+ if (Session::get_disable_all_loaded_plugins ()) {
+ info << _("Disabled LinuxVST scan (safe mode)") << endmsg;
+ return -1;
+ }
+
#ifndef NDEBUG
(void) path;
#endif
snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
info->unique_id = buf;
- info->category = "linuxVSTs";
+ info->category = finfo->Category;
info->path = path;
info->creator = finfo->creator;
info->index = 0;
info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
info->type = ARDOUR::LXVST;
- /* Make sure we don't find the same plugin in more than one place along
- the LXVST_PATH We can't use a simple 'find' because the path is included
- in the PluginInfo, and that is the one thing we can be sure MUST be
- different if a duplicate instance is found. So we just compare the type
- and unique ID (which for some VSTs isn't actually unique...)
- */
+ set_tags (info->type, info->unique_id, info->category, true);
+
+ /* Make sure we don't find the same plugin in more than one place along
+ * the LXVST_PATH We can't use a simple 'find' because the path is included
+ * in the PluginInfo, and that is the one thing we can be sure MUST be
+ * different if a duplicate instance is found. So we just compare the type
+ * and unique ID (which for some VSTs isn't actually unique...)
+ */
// TODO: check dup-IDs with windowsVST, too
bool duplicate = false;
PluginManager::PluginStatusType
-PluginManager::get_status (const PluginInfoPtr& pi)
+PluginManager::get_status (const PluginInfoPtr& pi) const
{
PluginStatus ps (pi->type, pi->unique_id);
PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), ps);
- if (i == statuses.end() ) {
+ if (i == statuses.end()) {
return Normal;
} else {
return i->status;
void
PluginManager::save_statuses ()
{
- std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
+ std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_statuses");
stringstream ofs;
for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
case LXVST:
ofs << "LXVST";
break;
+ case MacVST:
+ ofs << "MacVST";
+ break;
+ case Lua:
+ ofs << "Lua";
+ break;
}
ofs << ' ';
}
ofs << ' ';
+
ofs << (*i).unique_id;;
ofs << endl;
}
void
PluginManager::load_statuses ()
{
- std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
+ std::string path;
+ find_file (plugin_metadata_search_path(), "plugin_statuses", 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;
type = Windows_VST;
} else if (stype == "LXVST") {
type = LXVST;
+ } else if (stype == "MacVST") {
+ type = MacVST;
+ } else if (stype == "Lua") {
+ type = Lua;
} else {
error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
<< endmsg;
PluginStatus ps (t, id, status);
statuses.erase (ps);
- if (status == Normal) {
- return;
+ if (status != Normal) {
+ statuses.insert (ps);
+ }
+
+ PluginStatusesChanged (t, id, status); /* EMIT SIGNAL */
+}
+
+PluginType
+PluginManager::to_generic_vst (const PluginType t)
+{
+ switch (t) {
+ case Windows_VST:
+ case LXVST:
+ case MacVST:
+ return LXVST;
+ default:
+ break;
+ }
+ return t;
+}
+
+struct SortByTag {
+ bool operator() (std::string a, std::string b) {
+ return a.compare (b) < 0;
+ }
+};
+
+vector<std::string>
+PluginManager::get_tags (const PluginInfoPtr& pi) const
+{
+ vector<std::string> tags;
+
+ PluginTag ps (to_generic_vst(pi->type), pi->unique_id, "", false);
+ PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
+ if (i != ptags.end ()) {
+ PBD::tokenize (i->tags, string(" "), std::back_inserter (tags), true);
+ SortByTag sorter;
+ sort (tags.begin(), tags.end(), sorter);
+ }
+ return tags;
+}
+
+std::string
+PluginManager::get_tags_as_string (PluginInfoPtr const& pi) const
+{
+ std::string ret;
+
+ vector<std::string> tags = get_tags(pi);
+ for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
+ if (t != tags.begin ()) {
+ ret.append(" ");
+ }
+ ret.append(*t);
+ }
+
+ return ret;
+}
+
+std::string
+PluginManager::user_plugin_metadata_dir () const
+{
+ std::string dir = Glib::build_filename (user_config_directory(), plugin_metadata_dir_name);
+ g_mkdir_with_parents (dir.c_str(), 0744);
+ return dir;
+}
+
+void
+PluginManager::save_tags ()
+{
+ std::string path = Glib::build_filename (user_plugin_metadata_dir(), "plugin_tags");
+ XMLNode* root = new XMLNode (X_("PluginTags"));
+
+ for (PluginTagList::iterator i = ptags.begin(); i != ptags.end(); ++i) {
+ if (!(*i).user_set) {
+ continue;
+ }
+ XMLNode* node = new XMLNode (X_("Plugin"));
+ node->set_property (X_("type"), to_generic_vst ((*i).type));
+ node->set_property (X_("id"), (*i).unique_id);
+ node->set_property (X_("tags"), (*i).tags);
+ node->set_property (X_("user-set"), (*i).user_set);
+ root->add_child_nocopy (*node);
+ }
+
+ XMLTree tree;
+ tree.set_root (root);
+ if (!tree.write (path)) {
+ error << string_compose (_("Could not save Plugin Tags info to %1"), path) << endmsg;
+ }
+}
+
+void
+PluginManager::load_tags ()
+{
+ vector<std::string> tmp;
+ find_files_matching_pattern (tmp, plugin_metadata_search_path (), "plugin_tags");
+
+ for (vector<std::string>::const_reverse_iterator p = tmp.rbegin (); p != tmp.rend(); ++p) {
+ std::string path = *p;
+ info << string_compose (_("Loading plugin meta data file %1"), path) << endmsg;
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
+ return;
+ }
+
+ XMLTree tree;
+ if (!tree.read (path)) {
+ error << string_compose (_("Cannot parse plugin tag info from %1"), path) << endmsg;
+ return;
+ }
+
+ for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) {
+ PluginType type;
+ string id;
+ string tags;
+ bool user_set;
+ if (!(*i)->get_property (X_("type"), type) ||
+ !(*i)->get_property (X_("id"), id) ||
+ !(*i)->get_property (X_("tags"), tags)) {
+ }
+ if (!(*i)->get_property (X_("user-set"), user_set)) {
+ user_set = false;
+ }
+ strip_whitespace_edges (tags);
+ set_tags (type, id, tags, !user_set);
+ }
+ }
+}
+
+void
+PluginManager::set_tags (PluginType t, string id, string tag, bool factory, bool force)
+{
+ string sanitized = sanitize_tag (tag);
+
+ PluginTag ps (to_generic_vst (t), id, sanitized, !factory);
+ PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
+ if (i == ptags.end()) {
+ ptags.insert (ps);
+ } else if (!factory || force || !(*i).user_set) {
+ ptags.erase (ps);
+ ptags.insert (ps);
+ }
+ if (!factory || force) {
+ PluginTagsChanged (t, id, sanitized); /* EMIT SIGNAL */
+ }
+}
+
+void
+PluginManager::reset_tags (PluginInfoPtr const& pi)
+{
+ set_tags (pi->type, pi->unique_id, pi->category, true, true);
+}
+
+std::string
+PluginManager::sanitize_tag (const std::string to_sanitize) const
+{
+ if (to_sanitize.empty ()) {
+ return "";
+ }
+ string sanitized = to_sanitize;
+ vector<string> tags;
+ if (!PBD::tokenize (sanitized, string(" ,\n"), std::back_inserter (tags), true)) {
+#ifndef NDEBUG
+ cerr << _("PluginManager::sanitize_tag could not tokenize string: ") << sanitized << endmsg;
+#endif
+ return "";
+ }
+
+ /* convert tokens to lower-case, space-separated list */
+ sanitized = "";
+ for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
+ if (t != tags.begin ()) {
+ sanitized.append(" ");
+ }
+ sanitized.append (downcase (*t));
+ }
+
+ return sanitized;
+}
+
+std::vector<std::string>
+PluginManager::get_all_tags (bool favorites_only) const
+{
+ std::vector<std::string> ret;
+
+ PluginTagList::const_iterator pt;
+ for (pt = ptags.begin(); pt != ptags.end(); ++pt) {
+ if ((*pt).tags.empty ()) {
+ continue;
+ }
+
+ /* if favorites_only then we need to check the info ptr and maybe skip */
+ if (favorites_only) {
+ PluginStatus stat ((*pt).type, (*pt).unique_id);
+ PluginStatusList::const_iterator i = find (statuses.begin(), statuses.end(), stat);
+ if ((i != statuses.end()) && (i->status == Favorite)) {
+ /* it's a favorite! */
+ } else {
+ continue;
+ }
+ }
+
+ /* parse each plugin's tag string into separate tags */
+ vector<string> tags;
+ if (!PBD::tokenize ((*pt).tags, string(" "), std::back_inserter (tags), true)) {
+#ifndef NDEBUG
+ cerr << _("PluginManager: Could not tokenize string: ") << (*pt).tags << endmsg;
+#endif
+ continue;
+ }
+
+ /* maybe add the tags we've found */
+ for (vector<string>::iterator t = tags.begin(); t != tags.end(); ++t) {
+ /* if this tag isn't already in the list, add it */
+ vector<string>::iterator i = find (ret.begin(), ret.end(), *t);
+ if (i == ret.end()) {
+ ret.push_back (*t);
+ }
+ }
}
- statuses.insert (ps);
+ /* sort in alphabetical order */
+ SortByTag sorter;
+ sort (ret.begin(), ret.end(), sorter);
+
+ return ret;
}
-ARDOUR::PluginInfoList&
+
+const ARDOUR::PluginInfoList&
PluginManager::windows_vst_plugin_info ()
{
#ifdef WINDOWS_VST_SUPPORT
#endif
}
-ARDOUR::PluginInfoList&
+const ARDOUR::PluginInfoList&
+PluginManager::mac_vst_plugin_info ()
+{
+#ifdef MACVST_SUPPORT
+ assert(_mac_vst_plugin_info);
+ return *_mac_vst_plugin_info;
+#else
+ return _empty_plugin_info;
+#endif
+}
+
+const ARDOUR::PluginInfoList&
PluginManager::lxvst_plugin_info ()
{
#ifdef LXVST_SUPPORT
#endif
}
-ARDOUR::PluginInfoList&
+const ARDOUR::PluginInfoList&
PluginManager::ladspa_plugin_info ()
{
assert(_ladspa_plugin_info);
return *_ladspa_plugin_info;
}
-ARDOUR::PluginInfoList&
+const ARDOUR::PluginInfoList&
PluginManager::lv2_plugin_info ()
{
#ifdef LV2_SUPPORT
#endif
}
-ARDOUR::PluginInfoList&
+const ARDOUR::PluginInfoList&
PluginManager::au_plugin_info ()
{
#ifdef AUDIOUNIT_SUPPORT
#endif
return _empty_plugin_info;
}
+
+const ARDOUR::PluginInfoList&
+PluginManager::lua_plugin_info ()
+{
+ assert(_lua_plugin_info);
+ return *_lua_plugin_info;
+}