X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fvst_info_file.cc;h=3b56876494b93b8bcfbec016736540a4635cecee;hb=8367b7cab344e75908744a95fda860c7fadff420;hp=d7b83fcab8214fa0690ba099a0d9df0286e82c52;hpb=6442f316d4fa49847d19a3cb6b27dff45f588881;p=ardour.git diff --git a/libs/ardour/vst_info_file.cc b/libs/ardour/vst_info_file.cc index d7b83fcab8..3b56876494 100644 --- a/libs/ardour/vst_info_file.cc +++ b/libs/ardour/vst_info_file.cc @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -43,8 +42,9 @@ #include "pbd/error.h" #ifndef VST_SCANNER_APP -#include "pbd/system_exec.h" #include "ardour/plugin_manager.h" // scanner_bin_path +#include "ardour/rc_configuration.h" +#include "ardour/system_exec.h" #endif #include "ardour/filesystem_paths.h" @@ -53,12 +53,25 @@ #include "ardour/vst_info_file.h" #define MAX_STRING_LEN 256 -#define PLUGIN_SCAN_TIMEOUT (600) // in deciseconds +#define PLUGIN_SCAN_TIMEOUT (Config->get_vst_scan_timeout()) // in deciseconds -using namespace std; -// TODO: namespace public API into ARDOUR, ::Session or ::PluginManager -// consolidate vstfx_get_info_lx() and vstfx_get_info_fst() +/* CACHE FILE PATHS */ +#define EXT_BLACKLIST ".fsb" +#define EXT_ERRORFILE ".err" +#define EXT_INFOFILE ".fsi" + +#ifdef PLATFORM_WINDOWS +#define PFX_DOTFILE "" +#else +#define PFX_DOTFILE "." +#endif + + +using namespace std; +#ifndef VST_SCANNER_APP +namespace ARDOUR { +#endif /* prototypes */ #ifdef WINDOWS_VST_SUPPORT @@ -71,43 +84,62 @@ vstfx_instantiate_and_get_info_fst (const char* dllpath, vector *infos static bool vstfx_instantiate_and_get_info_lx (const char* dllpath, vector *infos, int uniqueID); #endif +/* ID for shell plugins */ static int vstfx_current_loading_id = 0; -static char * -read_string (FILE *fp) -{ - char buf[MAX_STRING_LEN]; - if (!fgets (buf, MAX_STRING_LEN, fp)) { - return 0; - } - if (strlen(buf) < MAX_STRING_LEN) { - if (strlen (buf)) { - buf[strlen(buf)-1] = 0; - } - return strdup (buf); +/* *** CACHE FILE PATHS *** */ + +static string +vstfx_cache_file (const char* dllpath, int personal, const char *ext) +{ + string dir; + if (personal) { + dir = get_personal_vst_info_cache_dir(); + // TODO prefix path relative to scan-root to avoid duplicates } else { - return 0; + dir = Glib::path_get_dirname (std::string(dllpath)); } + + stringstream s; + s << PFX_DOTFILE << Glib::path_get_basename (dllpath) << ext; + return Glib::build_filename (dir, s.str ()); } -/** Read an integer value from a line in fp into n, - * @return true on failure, false on success. - */ -static bool -read_int (FILE* fp, int* n) +static string +vstfx_blacklist_path (const char* dllpath, int personal) { - char buf[MAX_STRING_LEN]; - - char* p = fgets (buf, MAX_STRING_LEN, fp); - if (p == 0) { - return true; + string dir; + if (personal) { + dir = get_personal_vst_blacklist_dir(); + } else { + dir = Glib::path_get_dirname (std::string(dllpath)); } - return (sscanf (p, "%d", n) != 1); + stringstream s; + s << PFX_DOTFILE << Glib::path_get_basename (dllpath) << EXT_BLACKLIST; + return Glib::build_filename (dir, s.str ()); } +static string +vstfx_infofile_path (const char* dllpath, int personal) +{ + return vstfx_cache_file(dllpath, personal, EXT_INFOFILE); +} + +#ifndef VST_SCANNER_APP +static string +vstfx_errorfile_path (const char* dllpath, int personal) +{ + return vstfx_cache_file(dllpath, personal, EXT_ERRORFILE); +} +#endif + + +/* *** MEMORY MANAGEMENT *** */ + +/** cleanup single allocated VSTInfo */ static void vstfx_free_info (VSTInfo *info) { @@ -124,6 +156,7 @@ vstfx_free_info (VSTInfo *info) free (info); } +/** reset vector */ static void vstfx_clear_info_list (vector *infos) { @@ -133,6 +166,49 @@ vstfx_clear_info_list (vector *infos) infos->clear(); } + + +/* *** CACHE FILE I/O *** */ + +/** Helper function to read a line from the cache file + * @return newly allocated string of NULL + */ +static char * +read_string (FILE *fp) +{ + char buf[MAX_STRING_LEN]; + + if (!fgets (buf, MAX_STRING_LEN, fp)) { + return 0; + } + + if (strlen(buf) < MAX_STRING_LEN) { + if (strlen (buf)) { + buf[strlen(buf)-1] = 0; + } + return strdup (buf); + } else { + return 0; + } +} + +/** Read an integer value from a line in fp into n, + * @return true on failure, false on success. + */ +static bool +read_int (FILE* fp, int* n) +{ + char buf[MAX_STRING_LEN]; + + char* p = fgets (buf, MAX_STRING_LEN, fp); + if (p == 0) { + return true; + } + + return (sscanf (p, "%d", n) != 1); +} + +/** parse a plugin-block from the cache info file */ static bool vstfx_load_info_block(FILE* fp, VSTInfo *info) { @@ -152,6 +228,12 @@ vstfx_load_info_block(FILE* fp, VSTInfo *info) info->wantMidi = 1; } + if ((info->numParams) == 0) { + info->ParamNames = NULL; + info->ParamLabels = NULL; + return true; + } + if ((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == 0) { return false; } @@ -172,6 +254,7 @@ vstfx_load_info_block(FILE* fp, VSTInfo *info) return true; } +/** parse all blocks in a cache info file */ static bool vstfx_load_info_file (FILE* fp, vector *infos) { @@ -185,7 +268,7 @@ vstfx_load_info_file (FILE* fp, vector *infos) } else { int plugin_cnt = 0; vstfx_free_info(info); - if (read_int (fp, &plugin_cnt)) { + if (!read_int (fp, &plugin_cnt)) { for (int i = 0; i < plugin_cnt; i++) { if ((info = (VSTInfo*) calloc (1, sizeof (VSTInfo))) == 0) { vstfx_clear_info_list(infos); @@ -261,28 +344,22 @@ vstfx_write_info_file (FILE* fp, vector *infos) } } -static string -vstfx_blacklist_path (const char* dllpath, int personal) -{ - string dir; - if (personal) { - dir = get_personal_vst_blacklist_dir(); - } else { - dir = Glib::path_get_dirname (std::string(dllpath)); - } - stringstream s; - s << "." << Glib::path_get_basename (dllpath) << ".fsb"; - return Glib::build_filename (dir, s.str ()); -} +/* *** CACHE AND BLACKLIST MANAGEMENT *** */ /* return true if plugin is blacklisted or has an invalid file extension */ static bool vstfx_blacklist_stat (const char *dllpath, int personal) { - if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) { + const size_t slen = strlen (dllpath); + if ( + (slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so")) + && + (slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll")) + ) { return true; } + string const path = vstfx_blacklist_path (dllpath, personal); if (Glib::file_test (path, Glib::FileTest (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR))) { @@ -302,6 +379,8 @@ vstfx_blacklist_stat (const char *dllpath, int personal) return false; } +/* return true if plugin is blacklisted, checks both personal + * and global folder */ static bool vstfx_check_blacklist (const char *dllpath) { @@ -310,16 +389,26 @@ vstfx_check_blacklist (const char *dllpath) return false; } +/* create blacklist file, preferably in same folder as the + * plugin, fall back to personal folder in $HOME + */ static FILE * vstfx_blacklist_file (const char *dllpath) { FILE *f; - if ((f = fopen (vstfx_blacklist_path (dllpath, 0).c_str(), "w"))) { + if ((f = fopen (vstfx_blacklist_path (dllpath, 0).c_str(), "wb"))) { +#ifndef NDEBUG + PBD::info << "Blacklisted VST: '" << vstfx_blacklist_path (dllpath, 0) << "'" << endmsg; +#endif return f; } - return fopen (vstfx_blacklist_path (dllpath, 1).c_str(), "w"); +#ifndef NDEBUG + PBD::info << "Blacklisted VST: '" << vstfx_blacklist_path (dllpath, 1) << "'" << endmsg; +#endif + return fopen (vstfx_blacklist_path (dllpath, 1).c_str(), "wb"); } +/** mark plugin as blacklisted */ static bool vstfx_blacklist (const char *dllpath) { @@ -331,6 +420,7 @@ vstfx_blacklist (const char *dllpath) return false; } +/** mark plugin as not blacklisted */ static void vstfx_un_blacklist (const char *dllpath) { @@ -338,21 +428,7 @@ vstfx_un_blacklist (const char *dllpath) ::g_unlink(vstfx_blacklist_path (dllpath, 1).c_str()); } -static string -vstfx_infofile_path (const char* dllpath, int personal) -{ - string dir; - if (personal) { - dir = get_personal_vst_info_cache_dir(); - } else { - dir = Glib::path_get_dirname (std::string(dllpath)); - } - - stringstream s; - s << "." << Glib::path_get_basename (dllpath) << ".fsi"; - return Glib::build_filename (dir, s.str ()); -} - +/** remove info file from cache */ static void vstfx_remove_infofile (const char *dllpath) { @@ -360,10 +436,17 @@ vstfx_remove_infofile (const char *dllpath) ::g_unlink(vstfx_infofile_path (dllpath, 1).c_str()); } +/** helper function, check if cache is newer than plugin + * @return path to cache file */ static char * vstfx_infofile_stat (const char *dllpath, struct stat* statbuf, int personal) { - if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) { + const size_t slen = strlen (dllpath); + if ( + (slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so")) + && + (slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll")) + ) { return 0; } @@ -386,7 +469,8 @@ vstfx_infofile_stat (const char *dllpath, struct stat* statbuf, int personal) return 0; } - +/** cache file for given plugin + * @return FILE of the .fsi cache if found and up-to-date*/ static FILE * vstfx_infofile_for_read (const char* dllpath) { @@ -415,17 +499,31 @@ vstfx_infofile_for_read (const char* dllpath) return rv; } +/** helper function for \ref vstfx_infofile_for_write + * abstract global and personal cache folders + */ static FILE * vstfx_infofile_create (const char* dllpath, int personal) { - if (strstr (dllpath, ".so" ) == 0 && strstr(dllpath, ".dll") == 0) { - return 0; + const size_t slen = strlen (dllpath); + if ( + (slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so")) + && + (slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll")) + ) { + return NULL; } string const path = vstfx_infofile_path (dllpath, personal); - return fopen (path.c_str(), "w"); +#ifndef NDEBUG + PBD::info << "Creating VST cache file " << path << endmsg; +#endif + return fopen (path.c_str(), "wb"); } +/** newly created cache file for given plugin + * @return FILE for the .fsi cache, NULL if neither personal, + * nor global cache folder is writable */ static FILE * vstfx_infofile_for_write (const char* dllpath) { @@ -438,6 +536,29 @@ vstfx_infofile_for_write (const char* dllpath) return f; } +/** check if cache-file exists, is up-to-date and parse cache file + * @param infos [return] loaded plugin info + * @return true if .fsi cache was read successfully, false otherwise + */ +static bool +vstfx_get_info_from_file(const char* dllpath, vector *infos) +{ + FILE* infofile; + bool rv = false; + if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) { + rv = vstfx_load_info_file(infofile, infos); + fclose (infofile); + if (!rv) { + PBD::warning << "Cannot get VST information form " << dllpath << ": info file load failed." << endmsg; + } + } + return rv; +} + + + +/* *** VST system-under-test methods *** */ + static bool vstfx_midi_input (VSTState* vstfx) { @@ -448,7 +569,7 @@ bool vstfx_midi_input (VSTState* vstfx) if (vst_version >= 2) { /* should we send it VST events (i.e. MIDI) */ - if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)) { + if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast ("receiveVstEvents"), 0.0f) > 0)) { return true; } } @@ -466,8 +587,8 @@ bool vstfx_midi_output (VSTState* vstfx) if (vst_version >= 2) { /* should we send it VST events (i.e. MIDI) */ - if ( (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "sendVstEvents", 0.0f) > 0) - || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "sendVstMidiEvent", 0.0f) > 0) + if ( (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast ("sendVstEvents"), 0.0f) > 0) + || (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast ("sendVstMidiEvent"), 0.0f) > 0) ) { return true; } @@ -476,6 +597,46 @@ bool vstfx_midi_output (VSTState* vstfx) return false; } +/** simple 'dummy' audiomaster callback to instantiate the plugin + * and query information + */ +static intptr_t +simple_master_callback (AEffect *, int32_t opcode, int32_t, intptr_t, void *ptr, float) +{ + const char* vstfx_can_do_strings[] = { + "supplyIdle", + "sendVstTimeInfo", + "sendVstEvents", + "sendVstMidiEvent", + "receiveVstEvents", + "receiveVstMidiEvent", + "supportShell", + "shellCategory", + "shellCategorycurID" + }; + const int vstfx_can_do_string_count = 9; + + if (opcode == audioMasterVersion) { + return 2400; + } + else if (opcode == audioMasterCanDo) { + for (int i = 0; i < vstfx_can_do_string_count; i++) { + if (! strcmp(vstfx_can_do_strings[i], (const char*)ptr)) { + return 1; + } + } + return 0; + } + else if (opcode == audioMasterCurrentId) { + return vstfx_current_loading_id; + } + else { + return 0; + } +} + + +/** main plugin query and test function */ static VSTInfo* vstfx_parse_vst_state (VSTState* vstfx) { @@ -490,14 +651,26 @@ vstfx_parse_vst_state (VSTState* vstfx) fail to implement getVendorString, and so won't stuff the string with any name*/ - char creator[65] = "Unknown\0"; + char creator[65] = "Unknown"; + char name[65] = ""; AEffect* plugin = vstfx->plugin; - info->name = strdup (vstfx->handle->name); + + plugin->dispatcher (plugin, effGetEffectName, 0, 0, name, 0); + + if (strlen(name) == 0) { + plugin->dispatcher (plugin, effGetProductString, 0, 0, name, 0); + } + + if (strlen(name) == 0) { + info->name = strdup (vstfx->handle->name); + } else { + info->name = strdup (name); + } /*If the plugin doesn't bother to implement GetVendorString we will - have pre-stuffed the string with 'Unkown' */ + have pre-stuffed the string with 'Unknown' */ plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0); @@ -557,122 +730,93 @@ vstfx_parse_vst_state (VSTState* vstfx) return info; } +/** wrapper around \ref vstfx_parse_vst_state, + * iterate over plugins in shell, translate VST-info into ardour VSTState + */ static void vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector *infos, enum ARDOUR::PluginType type) { assert(vstfx); VSTInfo *info; - if ((info = vstfx_parse_vst_state(vstfx))) { - infos->push_back(info); -#if 1 - /* If this plugin is a Shell and we are not already inside a shell plugin - * read the info for all of the plugins contained in this shell. - */ - if (!strncmp (info->Category, "Shell", 5) - && vstfx->handle->plugincnt == 1) { - int id; - vector< pair > ids; - AEffect *plugin = vstfx->plugin; - string path = vstfx->handle->path; - - do { - char name[65] = "Unknown\0"; - id = plugin->dispatcher (plugin, effShellGetNextPlugin, 0, 0, name, 0); - ids.push_back(std::make_pair(id, name)); - } while ( id != 0 ); - - switch(type) { + if (!(info = vstfx_parse_vst_state(vstfx))) { + return; + } + + infos->push_back(info); +#if 1 // shell-plugin support + /* If this plugin is a Shell and we are not already inside a shell plugin + * read the info for all of the plugins contained in this shell. + */ + if (!strncmp (info->Category, "Shell", 5) + && vstfx->handle->plugincnt == 1) { + int id; + vector< pair > ids; + AEffect *plugin = vstfx->plugin; + + do { + char name[65] = "Unknown"; + id = plugin->dispatcher (plugin, effShellGetNextPlugin, 0, 0, name, 0); + ids.push_back(std::make_pair(id, name)); + } while ( id != 0 ); + + switch(type) { #ifdef WINDOWS_VST_SUPPORT - case 1: fst_close(vstfx); break; + case ARDOUR::Windows_VST: fst_close(vstfx); break; #endif #ifdef LXVST_SUPPORT - case 2: vstfx_close (vstfx); break; + case ARDOUR::LXVST: vstfx_close (vstfx); break; #endif - default: assert(0); break; - } + default: assert(0); break; + } - for (vector< pair >::iterator x = ids.begin(); x != ids.end(); ++x) { - id = (*x).first; - if (id == 0) continue; - /* recurse vstfx_get_info() */ + for (vector< pair >::iterator x = ids.begin(); x != ids.end(); ++x) { + id = (*x).first; + if (id == 0) continue; + /* recurse vstfx_get_info() */ - bool ok; - switch (type) { // TODO use lib ardour's type + bool ok; + switch (type) { #ifdef WINDOWS_VST_SUPPORT - case ARDOUR::Windows_VST: ok = vstfx_instantiate_and_get_info_fst(dllpath, infos, id); break; + case ARDOUR::Windows_VST: ok = vstfx_instantiate_and_get_info_fst(dllpath, infos, id); break; #endif #ifdef LXVST_SUPPORT - case ARDOUR::LXVST: ok = vstfx_instantiate_and_get_info_lx(dllpath, infos, id); break; + case ARDOUR::LXVST: ok = vstfx_instantiate_and_get_info_lx(dllpath, infos, id); break; #endif - default: ok = false; + default: ok = false; + } + if (ok) { + // One shell (some?, all?) does not report the actual plugin name + // even after the shelled plugin has been instantiated. + // Replace the name of the shell with the real name. + info = infos->back(); + free (info->name); + + if ((*x).second.length() == 0) { + info->name = strdup("Unknown"); } - if (ok) { - // One shell (some?, all?) does not report the actual plugin name - // even after the shelled plugin has been instantiated. - // Replace the name of the shell with the real name. - info = infos->back(); - free (info->name); - - if ((*x).second.length() == 0) { - info->name = strdup("Unknown"); - } - else { - info->name = strdup ((*x).second.c_str()); - } + else { + info->name = strdup ((*x).second.c_str()); } } } + } else { + switch(type) { +#ifdef WINDOWS_VST_SUPPORT + case ARDOUR::Windows_VST: fst_close(vstfx); break; +#endif +#ifdef LXVST_SUPPORT + case ARDOUR::LXVST: vstfx_close (vstfx); break; #endif + default: assert(0); break; + } } +#endif } -/* A simple 'dummy' audiomaster callback which should be ok, - we will only be instantiating the plugin in order to get its info -*/ -static intptr_t -simple_master_callback (AEffect *, int32_t opcode, int32_t, intptr_t, void *ptr, float) -{ - const char* vstfx_can_do_strings[] = { - "supportShell", - "shellCategory" - }; - const int vstfx_can_do_string_count = 2; - if (opcode == audioMasterVersion) { - return 2400; - } - else if (opcode == audioMasterCanDo) { - for (int i = 0; i < vstfx_can_do_string_count; i++) { - if (! strcmp(vstfx_can_do_strings[i], (const char*)ptr)) { - return 1; - } - } - return 0; - } - else if (opcode == audioMasterCurrentId) { - return vstfx_current_loading_id; - } - else { - return 0; - } -} - -static bool -vstfx_get_info_from_file(const char* dllpath, vector *infos) -{ - FILE* infofile; - bool rv = false; - if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) { - rv = vstfx_load_info_file(infofile, infos); - fclose (infofile); - if (!rv) { - PBD::warning << "Cannot get LinuxVST information form " << dllpath << ": info file load failed." << endmsg; - } - } - return rv; -} +/* *** TOP-LEVEL PLUGIN INSTANTIATION FUNCTIONS *** */ #ifdef LXVST_SUPPORT static bool @@ -698,7 +842,6 @@ vstfx_instantiate_and_get_info_lx ( vstfx_info_from_plugin(dllpath, vstfx, infos, ARDOUR::LXVST); - vstfx_close (vstfx); vstfx_unload (h); return true; } @@ -728,20 +871,64 @@ vstfx_instantiate_and_get_info_fst ( vstfx_info_from_plugin(dllpath, vstfx, infos, ARDOUR::Windows_VST); - fst_close(vstfx); - //fst_unload(&h); // XXX -> fst_close() return true; } #endif + + +/* *** ERROR LOGGING *** */ #ifndef VST_SCANNER_APP + +static FILE * _errorlog_fd = 0; +static char * _errorlog_dll = 0; + static void parse_scanner_output (std::string msg, size_t /*len*/) { - // TODO write to blacklist or error file..? - PBD::error << "VST scanner: " << msg; + if (!_errorlog_fd && !_errorlog_dll) { + PBD::error << "VST scanner: " << msg; + return; + } + + if (!_errorlog_fd) { + if (!(_errorlog_fd = fopen(vstfx_errorfile_path(_errorlog_dll, 0).c_str(), "w"))) { + if (!(_errorlog_fd = fopen(vstfx_errorfile_path(_errorlog_dll, 1).c_str(), "w"))) { + PBD::error << "Cannot create plugin error-log for plugin " << _errorlog_dll; + free(_errorlog_dll); + _errorlog_dll = NULL; + } + } + } + + if (_errorlog_fd) { + fprintf (_errorlog_fd, "%s\n", msg.c_str()); + } else { + PBD::error << "VST scanner: " << msg; + } } + +static void +set_error_log (const char* dllpath) { + assert(!_errorlog_fd); + assert(!_errorlog_dll); + _errorlog_dll = strdup(dllpath); +} + +static void +close_error_log () { + if (_errorlog_fd) { + fclose(_errorlog_fd); + _errorlog_fd = 0; + } + free(_errorlog_dll); + _errorlog_dll = 0; +} + #endif + +/* *** THE MAIN FUNCTION THAT USES ALL OF THE ABOVE :) *** */ + static vector * vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanMode mode) { @@ -771,15 +958,25 @@ vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanM argp[1] = strdup(dllpath); argp[2] = 0; - PBD::SystemExec scanner (scanner_bin_path, argp); + set_error_log(dllpath); + ARDOUR::SystemExec scanner (scanner_bin_path, argp); PBD::ScopedConnectionList cons; scanner.ReadStdout.connect_same_thread (cons, boost::bind (&parse_scanner_output, _1 ,_2)); if (scanner.start (2 /* send stderr&stdout via signal */)) { PBD::error << "Cannot launch VST scanner app '" << scanner_bin_path << "': "<< strerror(errno) << endmsg; + close_error_log(); return infos; } else { int timeout = PLUGIN_SCAN_TIMEOUT; - while (scanner.is_running() && --timeout) { + bool no_timeout = (timeout <= 0); + ARDOUR::PluginScanTimeout(timeout); + while (scanner.is_running() && (no_timeout || timeout > 0)) { + if (!no_timeout && !ARDOUR::PluginManager::instance().no_timeout()) { + if (timeout%5 == 0) { + ARDOUR::PluginScanTimeout(timeout); + } + --timeout; + } ARDOUR::GUIIdle(); Glib::usleep (100000); @@ -789,11 +986,13 @@ vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanM // remove temporary blacklist file (scan incomplete) vstfx_un_blacklist(dllpath); scanner.terminate(); + close_error_log(); return infos; } } scanner.terminate(); } + close_error_log(); /* re-read index (generated by external scanner) */ vstfx_clear_info_list(infos); if (!vstfx_check_blacklist(dllpath)) { @@ -839,6 +1038,8 @@ vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanM return infos; } + + /* *** public API *** */ void @@ -891,3 +1092,7 @@ vstfx_get_info_fst (char* dllpath, enum VSTScanMode mode) return vstfx_get_info(dllpath, ARDOUR::Windows_VST, mode); } #endif + +#ifndef VST_SCANNER_APP +} // namespace +#endif