diff --git a/libs/ardour/ardour/lxvst_plugin.h b/libs/ardour/ardour/lxvst_plugin.h index 596bbd8ca2..7b6492da6b 100644 --- a/libs/ardour/ardour/lxvst_plugin.h +++ b/libs/ardour/ardour/lxvst_plugin.h @@ -23,13 +23,11 @@ #include "ardour/vst_plugin.h" -struct _VSTHandle; -typedef struct _VSTHandle VSTHandle; - namespace ARDOUR { class AudioEngine; class Session; +struct VST2Info; class LIBARDOUR_API LXVSTPlugin : public VSTPlugin { @@ -44,7 +42,7 @@ class LIBARDOUR_API LXVSTPlugin : public VSTPlugin class LIBARDOUR_API LXVSTPluginInfo : public VSTPluginInfo { public: - LXVSTPluginInfo (_VSTInfo*); + LXVSTPluginInfo (VST2Info const&); ~LXVSTPluginInfo () {} PluginPtr load (Session& session); diff --git a/libs/ardour/ardour/mac_vst_plugin.h b/libs/ardour/ardour/mac_vst_plugin.h index 1a406b5945..98ca8d1946 100644 --- a/libs/ardour/ardour/mac_vst_plugin.h +++ b/libs/ardour/ardour/mac_vst_plugin.h @@ -28,6 +28,7 @@ namespace ARDOUR { class AudioEngine; class Session; +struct VST2Info; class LIBARDOUR_API MacVSTPlugin : public VSTPlugin { @@ -44,7 +45,7 @@ protected: class LIBARDOUR_API MacVSTPluginInfo : public VSTPluginInfo { public: - MacVSTPluginInfo (_VSTInfo*); + MacVSTPluginInfo (VST2Info const&); ~MacVSTPluginInfo () {} PluginPtr load (Session& session); diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h index 0da4c1b4e9..ebf22ac12e 100644 --- a/libs/ardour/ardour/plugin_manager.h +++ b/libs/ardour/ardour/plugin_manager.h @@ -48,10 +48,14 @@ class Plugin; struct VST3Info; #endif +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) +struct VST2Info; +#endif + class LIBARDOUR_API PluginManager : public boost::noncopyable { public: static PluginManager& instance(); - static std::string scanner_bin_path; + static std::string vst2_scanner_bin_path; static std::string vst3_scanner_bin_path; ~PluginManager (); @@ -296,10 +300,13 @@ private: void lv2_refresh (); int windows_vst_discover_from_path (std::string path, bool cache_only = false); - int windows_vst_discover (std::string path, bool cache_only = false); - int mac_vst_discover_from_path (std::string path, bool cache_only = false); - int mac_vst_discover (std::string path, bool cache_only = false); + int lxvst_discover_from_path (std::string path, bool cache_only = false); +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) + bool vst2_plugin (std::string const& module_path, ARDOUR::PluginType, VST2Info const&); + bool run_vst2_scanner_app (std::string bundle_path, PSLEPtr) const; + int vst2_discover (std::string path, ARDOUR::PluginType, bool cache_only = false); +#endif int vst3_discover_from_path (std::string const& path, bool cache_only = false); int vst3_discover (std::string const& path, bool cache_only = false); @@ -308,9 +315,6 @@ private: bool run_vst3_scanner_app (std::string bundle_path, PSLEPtr) const; #endif - int lxvst_discover_from_path (std::string path, bool cache_only = false); - int lxvst_discover (std::string path, bool cache_only = false); - int ladspa_discover (std::string path); std::string get_ladspa_category (uint32_t id); diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h index 78668cad31..353c71b1fe 100644 --- a/libs/ardour/ardour/vst_plugin.h +++ b/libs/ardour/ardour/vst_plugin.h @@ -34,11 +34,10 @@ typedef struct _VSTState VSTState; #include "ardour/vestige/vestige.h" -struct _VSTInfo; - namespace ARDOUR { class PluginInsert; +struct VST2Info; /** Parent class for VST plugins of both Windows and Linux varieties */ class LIBARDOUR_API VSTPlugin : public Plugin @@ -141,7 +140,7 @@ protected: class LIBARDOUR_API VSTPluginInfo : public PluginInfo { public: - VSTPluginInfo (_VSTInfo*); + VSTPluginInfo (VST2Info const&); bool is_instrument () const; protected: bool _is_instrument; diff --git a/libs/ardour/ardour/vst_types.h b/libs/ardour/ardour/vst_types.h index 3df795e108..33687e6987 100644 --- a/libs/ardour/ardour/vst_types.h +++ b/libs/ardour/ardour/vst_types.h @@ -52,29 +52,6 @@ struct LIBARDOUR_API _VSTKey typedef struct _VSTKey VSTKey; -struct LIBARDOUR_API _VSTInfo -{ - char *name; - char *creator; - int UniqueID; - char *Category; - - int numInputs; - int numOutputs; - int numParams; - - int wantMidi; - int wantEvents; - int hasEditor; - int isInstrument; // still unused - int canProcessReplacing; - - char** ParamNames; - char** ParamLabels; -}; - -typedef struct _VSTInfo VSTInfo; - typedef AEffect * (* main_entry_t) (audioMasterCallback); struct LIBARDOUR_API _VSTHandle diff --git a/libs/ardour/ardour/windows_vst_plugin.h b/libs/ardour/ardour/windows_vst_plugin.h index 7409de8b0c..0881eedf90 100644 --- a/libs/ardour/ardour/windows_vst_plugin.h +++ b/libs/ardour/ardour/windows_vst_plugin.h @@ -29,6 +29,7 @@ namespace ARDOUR { class AudioEngine; class Session; +struct VST2Info; class LIBARDOUR_API WindowsVSTPlugin : public VSTPlugin { @@ -43,7 +44,7 @@ public: class LIBARDOUR_API WindowsVSTPluginInfo : public VSTPluginInfo { public: - WindowsVSTPluginInfo (_VSTInfo*); + WindowsVSTPluginInfo (VST2Info const&); ~WindowsVSTPluginInfo () {} PluginPtr load (Session& session); diff --git a/libs/ardour/lxvst_plugin.cc b/libs/ardour/lxvst_plugin.cc index 297f33be6b..2f4689f779 100644 --- a/libs/ardour/lxvst_plugin.cc +++ b/libs/ardour/lxvst_plugin.cc @@ -167,8 +167,7 @@ LXVSTPluginInfo::get_presets (bool user_only) const return p; } -LXVSTPluginInfo::LXVSTPluginInfo (_VSTInfo* nfo) : VSTPluginInfo (nfo) +LXVSTPluginInfo::LXVSTPluginInfo (VST2Info const& nfo) : VSTPluginInfo (nfo) { type = ARDOUR::LXVST; } - diff --git a/libs/ardour/mac_vst_plugin.cc b/libs/ardour/mac_vst_plugin.cc index fdaa77b391..3c7bfa2df5 100644 --- a/libs/ardour/mac_vst_plugin.cc +++ b/libs/ardour/mac_vst_plugin.cc @@ -171,7 +171,7 @@ MacVSTPluginInfo::get_presets (bool user_only) const return p; } -MacVSTPluginInfo::MacVSTPluginInfo (_VSTInfo* nfo) : VSTPluginInfo (nfo) +MacVSTPluginInfo::MacVSTPluginInfo (VST2Info const& nfo) : VSTPluginInfo (nfo) { type = ARDOUR::MacVST; } diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index 0d733046a4..429714f4cf 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -47,30 +47,17 @@ #endif #ifdef WINDOWS_VST_SUPPORT -#include "ardour/vst_info_file.h" #include "fst.h" #include "pbd/basename.h" #include - -// dll-info -#include -#include -#include -#include - #endif // WINDOWS_VST_SUPPORT #ifdef LXVST_SUPPORT -#include "ardour/vst_info_file.h" -#include "ardour/linux_vst_support.h" #include "pbd/basename.h" #include #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 @@ -96,9 +83,11 @@ #include "ardour/plugin.h" #include "ardour/plugin_manager.h" #include "ardour/rc_configuration.h" - #include "ardour/search_paths.h" +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) +#include "ardour/vst2_scan.h" +#endif #ifdef WINDOWS_VST_SUPPORT #include "ardour/windows_vst_plugin.h" @@ -106,6 +95,12 @@ #ifdef LXVST_SUPPORT #include "ardour/lxvst_plugin.h" +#include "ardour/linux_vst_support.h" +#endif + +#ifdef MACVST_SUPPORT +#include "ardour/mac_vst_support.h" +#include "ardour/mac_vst_plugin.h" #endif #ifdef AUDIOUNIT_SUPPORT @@ -132,7 +127,7 @@ using namespace PBD; using namespace std; PluginManager* PluginManager::_instance = 0; -std::string PluginManager::scanner_bin_path = ""; +std::string PluginManager::vst2_scanner_bin_path = ""; std::string PluginManager::vst3_scanner_bin_path = ""; @@ -150,6 +145,14 @@ std::string PluginManager::vst3_scanner_bin_path = ""; # endif #endif +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) +# if ( defined(__x86_64__) || defined(_M_X64) ) +# define VST2_BLACKLIST "vst2_x64_blacklist.txt" +# else +# define VST2_BLACKLIST "vst2_x86_blacklist.txt" +# endif +#endif + PluginManager& PluginManager::instance() { @@ -201,7 +204,7 @@ PluginManager::PluginManager () #else "ardour-vst-scanner" #endif - , scanner_bin_path)) { + , vst2_scanner_bin_path)) { PBD::warning << "VST scanner app (ardour-vst-scanner) not found in path " << vstsp.to_string() << endmsg; } #endif // VST2 @@ -496,7 +499,7 @@ PluginManager::refresh (bool cache_only) #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); + string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST2_BLACKLIST); if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) { try { std::string bl = Glib::file_get_contents (fn); @@ -629,9 +632,9 @@ PluginManager::clear_vst_cache () #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT) { string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst"); - vector fsi_files; - find_files_matching_regex (fsi_files, dn, "\\" VST_EXT_INFOFILE "$", /* user cache is flat, no recursion */ false); - for (vector::iterator i = fsi_files.begin(); i != fsi_files.end (); ++i) { + vector v2i_files; + find_files_matching_regex (v2i_files, dn, "\\.v2i$", false); + for (vector::iterator i = v2i_files.begin(); i != v2i_files.end (); ++i) { ::g_unlink(i->c_str()); } } @@ -645,7 +648,7 @@ PluginManager::clear_vst_blacklist () { #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT) { - string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST); + string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST2_BLACKLIST); if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) { ::g_unlink (fn.c_str()); } @@ -1028,6 +1031,320 @@ PluginManager::au_refresh (bool cache_only) #endif +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) + +static void vst2_blacklist (string const& module_path) +{ + string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST2_BLACKLIST); + FILE* f = NULL; + if (! (f = g_fopen (fn.c_str (), "a"))) { + PBD::error << string_compose (_("Cannot write to VST2 blacklist file '%1'"), fn) << endmsg; + return; + } + assert (NULL == strchr (module_path.c_str(), '\n')); + fprintf (f, "%s\n", module_path.c_str ()); + ::fclose (f); +} + +static void vst2_whitelist (string module_path) +{ + string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST2_BLACKLIST); + if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) { + PBD::warning << _("Expected VST Blacklist file does not exist.") << endmsg; + return; + } + + std::string bl; + try { + bl = Glib::file_get_contents (fn); + } catch (Glib::FileError const& err) { + return; + } + ::g_unlink (fn.c_str ()); + + module_path += "\n"; // add separator + const size_t rpl = bl.find (module_path); + if (rpl != string::npos) { + bl.replace (rpl, module_path.size (), ""); + } + if (bl.empty ()) { + return; + } + Glib::file_set_contents (fn, bl); +} + +static bool vst2_is_blacklisted (string const& module_path) +{ + string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST2_BLACKLIST); + if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) { + return false; + } + + std::string bl; + try { + bl = Glib::file_get_contents (fn); + } catch (Glib::FileError const& err) { + return false; + } + return bl.find (module_path + "\n") != string::npos; +} + +static void vst2_scanner_log (std::string msg, PluginScanLogEntry* psle) +{ + psle->msg (PluginScanLogEntry::OK, msg); +} + +bool +PluginManager::run_vst2_scanner_app (std::string path, PSLEPtr psle) const +{ + char **argp= (char**) calloc (5, sizeof (char*)); + argp[0] = strdup (vst2_scanner_bin_path.c_str ()); + argp[1] = strdup ("-f"); + argp[2] = strdup ("-f"); // -v + argp[3] = strdup (path.c_str ()); + argp[4] = 0; + + ARDOUR::SystemExec scanner (vst2_scanner_bin_path, argp); + PBD::ScopedConnection c; + scanner.ReadStdout.connect_same_thread (c, boost::bind (&vst2_scanner_log, _1, &(*psle))); + + if (scanner.start (ARDOUR::SystemExec::MergeWithStdin)) { + psle->msg (PluginScanLogEntry::Error, string_compose (_("Cannot launch VST scanner app '%1': %2"), vst2_scanner_bin_path, strerror (errno))); + return false; + } + + int timeout = Config->get_vst_scan_timeout(); // deciseconds + bool notime = (timeout <= 0); + + while (scanner.is_running () && (notime || timeout > 0)) { + if (!notime && no_timeout ()) { + notime = true; + timeout = -1; + } + + ARDOUR::PluginScanTimeout (timeout); + --timeout; + Glib::usleep (100000); + + if (cancelled () || (!notime && timeout == 0)) { + scanner.terminate (); + if (cancelled ()) { + psle->msg (PluginScanLogEntry::New, "Scan was cancelled."); + } else { + psle->msg (PluginScanLogEntry::TimeOut, "Scan Timed Out."); + } + /* may be partially written */ + g_unlink (vst2_cache_file (path).c_str ()); + vst2_whitelist (path); + return false; + } + } + return true; +} + +bool +PluginManager::vst2_plugin (string const& path, PluginType type, VST2Info const& nfo) +{ + PSLEPtr psle (scan_log_entry (type, path)); + + if (!nfo.can_process_replace) { + psle->msg (PluginScanLogEntry::Error, string_compose (_("plugin '%1' does not support processReplacing, and so cannot be used in %2 at this time"), nfo.name, PROGRAM_NAME)); + return false; + } + + PluginInfoPtr info; + ARDOUR::PluginInfoList* plist; + + switch (type) { +#ifdef WINDOWS_VST_SUPPORT + case ARDOUR::Windows_VST: + info = PluginInfoPtr(new WindowsVSTPluginInfo (nfo)); + plist = _windows_vst_plugin_info; + break; +#endif +#ifdef LXVST_SUPPORT + case ARDOUR::LXVST: + info = PluginInfoPtr(new LXVSTPluginInfo (nfo)); + plist = _lxvst_plugin_info; + break; +#endif +#ifdef MACVST_SUPPORT + case ARDOUR::MacVST: + info = PluginInfoPtr(new MacVSTPluginInfo (nfo)); + plist = _mac_vst_plugin_info; + break; +#endif + default: + assert (0); + return false; + } + + info->path = path; + + /* what a joke freeware VST is */ + if (!strcasecmp ("The Unnamed plugin", info->name.c_str())) { + info->name = PBD::basename_nosuffix (path); + } + + /* 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...) + */ + + bool duplicate = false; + if (!plist->empty()) { + for (PluginInfoList::iterator i =plist->begin(); i != plist->end(); ++i) { + if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) { + psle->msg (PluginScanLogEntry::Error, string_compose (_("Ignoring plugin '%1'. VST-ID conflicts with other plugin '%2' files: '%3' vs '%4'"), info->name, (*i)->name, info->path, (*i)->path)); + duplicate = true; + continue; + } + } + } + + if (duplicate) { + return false; + } + + plist->push_back (info); + psle->add (info); + + if (!info->category.empty ()) { + set_tags (info->type, info->unique_id, info->category, info->name, FromPlug); + } + return true; +} + +int +PluginManager::vst2_discover (string path, ARDOUR::PluginType type, bool cache_only) +{ + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent VST plugin at %1\n", path)); + + PSLEPtr psle (scan_log_entry (type, path)); + + if (vst2_is_blacklisted (path)) { + psle->msg (PluginScanLogEntry::Blacklisted); + return -1; + } + + bool run_scan = false; + bool is_new = false; + + string cache_file = vst2_valid_cache_file (path, false, &is_new); + + if (!cache_only && vst2_scanner_bin_path.empty () && cache_file.empty ()) { + /* scan in host context */ + psle->reset (); + vst2_blacklist (path); + psle->msg (PluginScanLogEntry::OK, string_compose ("VST2 plugin: '%1' (internal scan)", path)); + + if (!vst2_scan_and_cache (path, type, sigc::mem_fun (*this, &PluginManager::vst2_plugin))) { + psle->msg (PluginScanLogEntry::Error, "Cannot load VST2"); + psle->msg (PluginScanLogEntry::Blacklisted); + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot load VST2 at '%1'\n", path)); + return -1; + } + psle->msg (PluginScanLogEntry::OK, string_compose (_("Saved VST2 plugin cache to '%1'"), vst2_cache_file (path))); + vst2_whitelist (path); + return 0; + } + + + XMLTree tree; + if (cache_file.empty ()) { + run_scan = true; + } else if (tree.read (cache_file)) { + /* valid cache file was found, now check version */ + int cf_version = 0; + if (!tree.root()->get_property ("version", cf_version) || cf_version < 1) { + run_scan = true; + } + } else { + /* failed to parse XML */ + run_scan = true; + } + + if (!cache_only && run_scan) { + /* re/generate cache file */ + psle->reset (); + vst2_blacklist (path); + + if (!run_vst2_scanner_app (path, psle)) { + return -1; + } + + cache_file = vst2_valid_cache_file (path); + + if (cache_file.empty ()) { + psle->msg (PluginScanLogEntry::Error, _("Scan Failed.")); + psle->msg (PluginScanLogEntry::Blacklisted); + return -1; + } + /* re-read cache file */ + if (!tree.read (cache_file)) { + psle->msg (PluginScanLogEntry::Error, string_compose (_("Cannot parse VST2 cache file '%1' for plugin '%2'"), cache_file, path)); + psle->msg (PluginScanLogEntry::Blacklisted); + return -1; + } + run_scan = false; // mark as scanned + } + + if (cache_file.empty () || run_scan) { + /* cache file does not exist and cache_only == true, + * or cache file is invalid (scan needed) + */ + psle->msg (is_new ? PluginScanLogEntry::New : PluginScanLogEntry::Updated); + return -1; + } + + std::string binary; + if (!tree.root()->get_property ("binary", binary) || binary != path) { + psle->msg (PluginScanLogEntry::Incompatible, string_compose (_("Invalid VST2 cache file '%1'"), cache_file)); // XXX log as error msg + psle->msg (PluginScanLogEntry::Blacklisted); + if (!vst2_is_blacklisted (path)) { + vst2_blacklist (path); + } + return -1; + } + + std::string arch; + if (!tree.root()->get_property ("arch", arch) || arch != vst2_arch ()) { + if (!vst2_is_blacklisted (path)) { + vst2_blacklist (path); + } + psle->msg (PluginScanLogEntry::Blacklisted); + psle->msg (PluginScanLogEntry::Incompatible, string_compose (_("VST2 architecture mismatches '%1'"), arch)); + return -1; + } + + vst2_whitelist (path); + psle->set_result (PluginScanLogEntry::OK); + + uint32_t discovered = 0; + for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) { + try { + VST2Info nfo (**i); + if (vst2_plugin (path, type, nfo)) { + ++discovered; + } else { + psle->msg (PluginScanLogEntry::Blacklisted); + vst2_blacklist (path); + } + } catch (...) { + psle->msg (PluginScanLogEntry::Error, string_compose (_("Corrupt VST2 cache file '%1'"), cache_file)); + DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot load VST2 at '%1'\n", path)); + continue; + } + } + + return discovered; +} + +#endif + + #ifdef WINDOWS_VST_SUPPORT void @@ -1074,7 +1391,7 @@ PluginManager::windows_vst_discover_from_path (string path, bool cache_only) for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) { ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled()); - windows_vst_discover (*x, cache_only || cancelled()); + vst2_discover (*x, Windows_VST, cache_only || cancelled()); } if (Config->get_verbose_plugin_scan()) { @@ -1083,144 +1400,6 @@ PluginManager::windows_vst_discover_from_path (string path, bool cache_only) return ret; } - -static std::string dll_info (std::string path) { - std::string rv; - uint8_t buf[68]; - uint16_t type = 0; - off_t pe_hdr_off = 0; - - int fd = g_open(path.c_str(), O_RDONLY, 0444); - - if (fd < 0) { - return _("cannot open dll"); // TODO strerror() - } - - if (68 != read (fd, buf, 68)) { - rv = _("invalid dll, file too small"); - goto errorout; - } - if (buf[0] != 'M' && buf[1] != 'Z') { - rv = _("not a dll"); - goto errorout; - } - - pe_hdr_off = *((int32_t*) &buf[60]); - if (pe_hdr_off !=lseek (fd, pe_hdr_off, SEEK_SET)) { - rv = _("cannot determine dll type"); - goto errorout; - } - if (6 != read (fd, buf, 6)) { - rv = _("cannot read dll PE header"); - goto errorout; - } - - if (buf[0] != 'P' && buf[1] != 'E') { - rv = _("invalid dll PE header"); - goto errorout; - } - - type = *((uint16_t*) &buf[4]); - switch (type) { - case 0x014c: - rv = _("i386 (32-bit)"); - break; - case 0x0200: - rv = _("Itanium"); - break; - case 0x8664: - rv = _("x64 (64-bit)"); - break; - case 0: - rv = _("Native Architecture"); - break; - default: - rv = _("Unknown Architecture"); - break; - } -errorout: - assert (rv.length() > 0); - close (fd); - return rv; -} - -int -PluginManager::windows_vst_discover (string path, bool cache_only) -{ - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path)); - - if (Config->get_verbose_plugin_scan()) { - if (cache_only) { - info << string_compose (_(" * %1 (cache only)"), path) << endmsg; - } else { - info << string_compose (_(" * %1 - %2"), path, dll_info (path)) << endmsg; - } - } - - _cancel_timeout = false; - vector * finfos = vstfx_get_info_fst (const_cast (path.c_str()), - cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP); - - // TODO get extended error messae from vstfx_get_info_fst() e.g blacklisted, 32/64bit compat, - // .err file scanner output etc. - - if (finfos->empty()) { - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path)); - if (Config->get_verbose_plugin_scan()) { - info << _(" -> Cannot get Windows VST information, plugin ignored.") << endmsg; - } - return -1; - } - - uint32_t discovered = 0; - for (vector::iterator x = finfos->begin(); x != finfos->end(); ++x) { - VSTInfo* finfo = *x; - - if (!finfo->canProcessReplacing) { - warning << string_compose (_("VST plugin %1 does not support processReplacing, and cannot be used in %2 at this time"), - finfo->name, PROGRAM_NAME) - << endl; - continue; - } - - PluginInfoPtr info (new WindowsVSTPluginInfo (finfo)); - info->path = path; - - /* what a joke freeware VST is */ - if (!strcasecmp ("The Unnamed plugin", finfo->name)) { - info->name = PBD::basename_nosuffix (path); - } - - /* if we don't have any tags for this plugin, make some up. */ - set_tags (info->type, info->unique_id, info->category, info->name, FromPlug); - - // TODO: check dup-IDs (lxvst AND windows vst) - bool duplicate = false; - - if (!_windows_vst_plugin_info->empty()) { - for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) { - if ((info->type == (*i)->type) && (info->unique_id == (*i)->unique_id)) { - warning << string_compose (_("Ignoring duplicate Windows VST plugin \"%1\""), info->name) << endmsg; - duplicate = true; - break; - } - } - } - - if (!duplicate) { - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id)); - _windows_vst_plugin_info->push_back (info); - discovered++; - if (Config->get_verbose_plugin_scan()) { - PBD::info << string_compose (_(" -> OK (VST Plugin \"%1\" was added)."), info->name) << endmsg; - } - } - } - - vstfx_free_info_list (finfos); - return discovered > 0 ? 0 : -1; -} - #endif // WINDOWS_VST_SUPPORT #ifdef MACVST_SUPPORT @@ -1274,7 +1453,7 @@ PluginManager::mac_vst_discover_from_path (string path, bool cache_only) if (mac_vst_filter (fullpath)) { ARDOUR::PluginScanMessage(_("MacVST"), fullpath, !cache_only && !cancelled()); - mac_vst_discover (fullpath, cache_only || cancelled()); + vst2_discover (fullpath, MacVST, cache_only || cancelled()); continue; } @@ -1292,59 +1471,6 @@ PluginManager::mac_vst_discover_from_path (string path, bool cache_only) 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* finfos = vstfx_get_info_mac (const_cast (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::iterator x = finfos->begin(); x != finfos->end(); ++x) { - VSTInfo* finfo = *x; - - 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 (finfo)); - info->path = path; - - /* if we don't have any tags for this plugin, make some up. */ - set_tags (info->type, info->unique_id, info->category, info->name, FromPlug); - - 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 @@ -1394,75 +1520,12 @@ PluginManager::lxvst_discover_from_path (string path, bool cache_only) for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) { ARDOUR::PluginScanMessage(_("LXVST"), *x, !cache_only && !cancelled()); - lxvst_discover (*x, cache_only || cancelled()); + vst2_discover (*x, LXVST, cache_only || cancelled()); } return ret; } -int -PluginManager::lxvst_discover (string path, bool cache_only) -{ - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path)); - - _cancel_timeout = false; - vector * finfos = vstfx_get_info_lx (const_cast (path.c_str()), - cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP); - - if (finfos->empty()) { - DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path)); - return -1; - } - - uint32_t discovered = 0; - for (vector::iterator x = finfos->begin(); x != finfos->end(); ++x) { - VSTInfo* finfo = *x; - - if (!finfo->canProcessReplacing) { - warning << string_compose (_("linuxVST 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 LXVSTPluginInfo (finfo)); - info->path = path; - - if (!strcasecmp ("The Unnamed plugin", finfo->name)) { - info->name = PBD::basename_nosuffix (path); - } - - set_tags (info->type, info->unique_id, info->category, info->name, FromPlug); - - /* 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; - if (!_lxvst_plugin_info->empty()) { - for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) { - if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) { - warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n"; - duplicate = true; - break; - } - } - } - - if (!duplicate) { - _lxvst_plugin_info->push_back (info); - discovered++; - } - } - - vstfx_free_info_list (finfos); - return discovered > 0 ? 0 : -1; -} - #endif // LXVST_SUPPORT void diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 5637f3e9ec..33529f52c4 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -35,6 +35,7 @@ #include "ardour/vst_types.h" #include "ardour/vst_plugin.h" +#include "ardour/vst2_scan.h" #include "ardour/vestige/vestige.h" #include "ardour/session.h" #include "ardour/filesystem_paths.h" @@ -942,23 +943,25 @@ VSTPlugin::presets_file () const } -VSTPluginInfo::VSTPluginInfo (VSTInfo* nfo) +VSTPluginInfo::VSTPluginInfo (VST2Info const& nfo) { char buf[32]; - snprintf (buf, sizeof (buf), "%d", nfo->UniqueID); + snprintf (buf, sizeof (buf), "%d", nfo.id); unique_id = buf; index = 0; - name = nfo->name; - creator = nfo->creator; - n_inputs.set_audio (nfo->numInputs); - n_outputs.set_audio (nfo->numOutputs); - n_inputs.set_midi ((nfo->wantMidi & 1) ? 1 : 0); - n_outputs.set_midi ((nfo->wantMidi & 2) ? 1 : 0); + name = nfo.name; + creator = nfo.creator; + category = nfo.category; - _is_instrument = nfo->isInstrument; + n_inputs.set_audio (nfo.n_inputs); + n_outputs.set_audio (nfo.n_outputs); + n_inputs.set_midi (nfo.n_midi_inputs); + n_outputs.set_midi (nfo.n_midi_outputs); + + _is_instrument = nfo.is_instrument; } bool diff --git a/libs/ardour/windows_vst_plugin.cc b/libs/ardour/windows_vst_plugin.cc index 4244ce87be..b2d340d928 100644 --- a/libs/ardour/windows_vst_plugin.cc +++ b/libs/ardour/windows_vst_plugin.cc @@ -134,7 +134,7 @@ WindowsVSTPluginInfo::get_presets (bool user_only) const return p; } -WindowsVSTPluginInfo::WindowsVSTPluginInfo (_VSTInfo* nfo) : VSTPluginInfo (nfo) +WindowsVSTPluginInfo::WindowsVSTPluginInfo (VST2Info const& nfo) : VSTPluginInfo (nfo) { type = ARDOUR::Windows_VST; } diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 9f3f7e88f5..141579ea34 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -458,7 +458,7 @@ def build(bld): obj.defines += [ 'LXVST_SUPPORT' ] if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT') or bld.is_defined('MACVST_SUPPORT'): - obj.source += [ 'session_vst.cc', 'vst_plugin.cc', 'vst_info_file.cc', 'vst_state.cc' ] + obj.source += [ 'session_vst.cc', 'vst_plugin.cc', 'vst_state.cc', 'vst2_scan.cc' ] if bld.is_defined('MACVST_SUPPORT'): obj.source += [ 'mac_vst_plugin.cc', 'mac_vst_support.cc' ]