d77a01035caa4e91fa512b421a2a9c2aae22c2a8
[ardour.git] / libs / ardour / vst_info_file.cc
1 /*
2     Copyright (C) 2012-2014 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file libs/ardour/vst_info_file.cc
21  *  @brief Code to manage info files containing cached information about a plugin.
22  *  e.g. its name, creator etc.
23  */
24
25 #include <iostream>
26 #include <fstream>
27 #include <cassert>
28
29 #include <sys/types.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <errno.h>
33
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <string.h>
38
39 #include <glib.h>
40 #include <pbd/gstdio_compat.h>
41 #include <glibmm.h>
42
43 #include "pbd/error.h"
44 #include "pbd/compose.h"
45
46 #ifndef VST_SCANNER_APP
47 #include "ardour/plugin_manager.h" // scanner_bin_path
48 #include "ardour/rc_configuration.h"
49 #include "ardour/system_exec.h"
50 #endif
51
52 #include "ardour/filesystem_paths.h"
53 #include "ardour/linux_vst_support.h"
54 #include "ardour/plugin_types.h"
55 #include "ardour/vst_info_file.h"
56
57 #include "i18n.h"
58 #include "sha1.c"
59
60 #define MAX_STRING_LEN 256
61 #define PLUGIN_SCAN_TIMEOUT (Config->get_vst_scan_timeout()) // in deciseconds
62
63 using namespace std;
64 #ifndef VST_SCANNER_APP
65 namespace ARDOUR {
66 #endif
67
68 /* prototypes */
69 #ifdef WINDOWS_VST_SUPPORT
70 #include <fst.h>
71 static bool
72 vstfx_instantiate_and_get_info_fst (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
73 #endif
74
75 #ifdef LXVST_SUPPORT
76 static bool vstfx_instantiate_and_get_info_lx (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
77 #endif
78
79 /* ID for shell plugins */
80 static int vstfx_current_loading_id = 0;
81
82 /* *** CACHE FILE PATHS *** */
83
84 static string
85 get_vst_info_cache_dir () {
86         string dir = Glib::build_filename (ARDOUR::user_cache_directory (), "vst");
87         /* if the directory doesn't exist, try to create it */
88         if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR)) {
89                 if (g_mkdir (dir.c_str (), 0700)) {
90                         PBD::fatal << "Cannot create VST info folder '" << dir << "'" << endmsg;
91                 }
92         }
93         return dir;
94 }
95
96 static string
97 vstfx_infofile_path (const char* dllpath)
98 {
99         char hash[41];
100         Sha1Digest s;
101         sha1_init (&s);
102         sha1_write (&s, (const uint8_t *) dllpath, strlen (dllpath));
103         sha1_result_hash (&s, hash);
104         return Glib::build_filename (get_vst_info_cache_dir (), std::string (hash) + std::string (VST_EXT_INFOFILE));
105 }
106
107
108 /* *** VST Blacklist *** */
109
110 static void vstfx_read_blacklist (std::string &bl) {
111         FILE * blacklist_fd = NULL;
112         bl = "";
113
114         string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST_BLACKLIST);
115
116         if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
117                 return;
118         }
119
120         if (! (blacklist_fd = g_fopen (fn.c_str (), "rb"))) {
121                 return;
122         }
123
124         while (!feof (blacklist_fd)) {
125                 char buf[1024];
126                 size_t s = fread (buf, sizeof(char), 1024, blacklist_fd);
127                 if (ferror (blacklist_fd)) {
128                         PBD::error << string_compose (_("error reading VST Blacklist file %1 (%2)"), fn, strerror (errno)) << endmsg;
129                         bl = "";
130                         break;
131                 }
132                 if (s == 0) {
133                         break;
134                 }
135                 bl.append (buf, s);
136         }
137         ::fclose (blacklist_fd);
138 }
139
140 /** mark plugin as blacklisted */
141 static void vstfx_blacklist (const char *id)
142 {
143         string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST_BLACKLIST);
144         FILE * blacklist_fd = NULL;
145         if (! (blacklist_fd = g_fopen (fn.c_str (), "a"))) {
146                 PBD::error << string_compose (_("Cannot append to VST blacklist for '%1'"), id) << endmsg;
147                 return;
148         }
149         assert (NULL == strchr (id, '\n'));
150         fprintf (blacklist_fd, "%s\n", id);
151         ::fclose (blacklist_fd);
152 }
153
154 /** mark plugin as not blacklisted */
155 static void vstfx_un_blacklist (const char *idcs)
156 {
157         string id (idcs);
158         string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST_BLACKLIST);
159         if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
160                 PBD::warning << _("Expected VST Blacklist file does not exist.") << endmsg;
161                 return;
162         }
163
164         std::string bl;
165         vstfx_read_blacklist (bl);
166
167         ::g_unlink (fn.c_str ());
168
169         assert (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS));
170         assert (id.find ("\n") == string::npos);
171
172         id += "\n"; // add separator
173         const size_t rpl = bl.find (id);
174         if (rpl != string::npos) {
175                 bl.replace (rpl, id.size (), "");
176         }
177         if (bl.empty ()) {
178                 return;
179         }
180
181         FILE * blacklist_fd = NULL;
182         if (! (blacklist_fd = g_fopen (fn.c_str (), "w"))) {
183                 PBD::error << _("Cannot open VST blacklist.") << endmsg;;
184                 return;
185         }
186         fprintf (blacklist_fd, "%s", bl.c_str ());
187         ::fclose (blacklist_fd);
188 }
189
190 /* return true if plugin is blacklisted */
191 static bool vst_is_blacklisted (const char *idcs)
192 {
193         // TODO ideally we'd also check if the VST has been updated since blacklisting
194         string id (idcs);
195         string fn = Glib::build_filename (ARDOUR::user_cache_directory (), VST_BLACKLIST);
196         if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
197                 return false;
198         }
199
200         std::string bl;
201         vstfx_read_blacklist (bl);
202
203         assert (id.find ("\n") == string::npos);
204
205         id += "\n"; // add separator
206         const size_t rpl = bl.find (id);
207         if (rpl != string::npos) {
208                 return true;
209         }
210         return false;
211 }
212
213
214
215 /* *** MEMORY MANAGEMENT *** */
216
217 /** cleanup single allocated VSTInfo */
218 static void
219 vstfx_free_info (VSTInfo *info)
220 {
221         for (int i = 0; i < info->numParams; i++) {
222                 free (info->ParamNames[i]);
223                 free (info->ParamLabels[i]);
224         }
225
226         free (info->name);
227         free (info->creator);
228         free (info->Category);
229         free (info->ParamNames);
230         free (info->ParamLabels);
231         free (info);
232 }
233
234 /** reset vector */
235 static void
236 vstfx_clear_info_list (vector<VSTInfo *> *infos)
237 {
238         for (vector<VSTInfo *>::iterator i = infos->begin (); i != infos->end (); ++i) {
239                 vstfx_free_info (*i);
240         }
241         infos->clear ();
242 }
243
244
245 /* *** CACHE FILE I/O *** */
246
247 /** Helper function to read a line from the cache file
248  * @return newly allocated string of NULL
249  */
250 static char *
251 read_string (FILE *fp)
252 {
253         char buf[MAX_STRING_LEN];
254
255         if (!fgets (buf, MAX_STRING_LEN, fp)) {
256                 return 0;
257         }
258
259         if (strlen (buf) < MAX_STRING_LEN) {
260                 if (strlen (buf)) {
261                         buf[strlen (buf)-1] = 0;
262                 }
263                 return strdup (buf);
264         } else {
265                 return 0;
266         }
267 }
268
269 /** Read an integer value from a line in fp into n,
270  *  @return true on failure, false on success.
271  */
272 static bool
273 read_int (FILE* fp, int* n)
274 {
275         char buf[MAX_STRING_LEN];
276
277         char* p = fgets (buf, MAX_STRING_LEN, fp);
278         if (p == 0) {
279                 return true;
280         }
281
282         return (sscanf (p, "%d", n) != 1);
283 }
284
285 /** parse a plugin-block from the cache info file */
286 static bool
287 vstfx_load_info_block (FILE* fp, VSTInfo *info)
288 {
289         if ((info->name = read_string (fp)) == 0) return false;
290         if ((info->creator = read_string (fp)) == 0) return false;
291         if (read_int (fp, &info->UniqueID)) return false;
292         if ((info->Category = read_string (fp)) == 0) return false;
293         if (read_int (fp, &info->numInputs)) return false;
294         if (read_int (fp, &info->numOutputs)) return false;
295         if (read_int (fp, &info->numParams)) return false;
296         if (read_int (fp, &info->wantMidi)) return false;
297         if (read_int (fp, &info->hasEditor)) return false;
298         if (read_int (fp, &info->canProcessReplacing)) return false;
299
300         /* backwards compatibility with old .fsi files */
301         if (info->wantMidi == -1) {
302                 info->wantMidi = 1;
303         }
304
305         if ((info->numParams) == 0) {
306                 info->ParamNames = NULL;
307                 info->ParamLabels = NULL;
308                 return true;
309         }
310
311         if ((info->ParamNames = (char **) malloc (sizeof (char*) * info->numParams)) == 0) {
312                 return false;
313         }
314
315         for (int i = 0; i < info->numParams; ++i) {
316                 if ((info->ParamNames[i] = read_string (fp)) == 0) return false;
317         }
318
319         if ((info->ParamLabels = (char **) malloc (sizeof (char*) * info->numParams)) == 0) {
320                 return false;
321         }
322
323         for (int i = 0; i < info->numParams; ++i) {
324                 if ((info->ParamLabels[i] = read_string (fp)) == 0) {
325                         return false;
326                 }
327         }
328         return true;
329 }
330
331 /** parse all blocks in a cache info file */
332 static bool
333 vstfx_load_info_file (FILE* fp, vector<VSTInfo*> *infos)
334 {
335         VSTInfo *info;
336         if ((info = (VSTInfo*) calloc (1, sizeof (VSTInfo))) == 0) {
337                 return false;
338         }
339         if (vstfx_load_info_block (fp, info)) {
340                 if (strncmp (info->Category, "Shell", 5)) {
341                         infos->push_back (info);
342                 } else {
343                         int plugin_cnt = 0;
344                         vstfx_free_info (info);
345                         if (!read_int (fp, &plugin_cnt)) {
346                                 for (int i = 0; i < plugin_cnt; i++) {
347                                         if ((info = (VSTInfo*) calloc (1, sizeof (VSTInfo))) == 0) {
348                                                 vstfx_clear_info_list (infos);
349                                                 return false;
350                                         }
351                                         if (vstfx_load_info_block (fp, info)) {
352                                                 infos->push_back (info);
353                                         } else {
354                                                 vstfx_free_info (info);
355                                                 vstfx_clear_info_list (infos);
356                                                 return false;
357                                         }
358                                 }
359                         } else {
360                                 return false; /* Bad file */
361                         }
362                 }
363                 return true;
364         }
365         vstfx_free_info (info);
366         vstfx_clear_info_list (infos);
367         return false;
368 }
369
370 static void
371 vstfx_write_info_block (FILE* fp, VSTInfo *info)
372 {
373         assert (info);
374         assert (fp);
375
376         fprintf (fp, "%s\n", info->name);
377         fprintf (fp, "%s\n", info->creator);
378         fprintf (fp, "%d\n", info->UniqueID);
379         fprintf (fp, "%s\n", info->Category);
380         fprintf (fp, "%d\n", info->numInputs);
381         fprintf (fp, "%d\n", info->numOutputs);
382         fprintf (fp, "%d\n", info->numParams);
383         fprintf (fp, "%d\n", info->wantMidi);
384         fprintf (fp, "%d\n", info->hasEditor);
385         fprintf (fp, "%d\n", info->canProcessReplacing);
386
387         for (int i = 0; i < info->numParams; i++) {
388                 fprintf (fp, "%s\n", info->ParamNames[i]);
389         }
390
391         for (int i = 0; i < info->numParams; i++) {
392                 fprintf (fp, "%s\n", info->ParamLabels[i]);
393         }
394 }
395
396 static void
397 vstfx_write_info_file (FILE* fp, vector<VSTInfo *> *infos)
398 {
399         assert (infos);
400         assert (fp);
401
402         if (infos->size () > 1) {
403                 vector<VSTInfo *>::iterator x = infos->begin ();
404                 /* write out the shell info first along with count of the number of
405                  * plugins contained in this shell
406                  */
407                 vstfx_write_info_block (fp, *x);
408                 fprintf (fp, "%d\n", (int)infos->size () - 1 );
409                 ++x;
410                 /* Now write out the info for each plugin */
411                 for (; x != infos->end (); ++x) {
412                         vstfx_write_info_block (fp, *x);
413                 }
414         } else if (infos->size () == 1) {
415                 vstfx_write_info_block (fp, infos->front ());
416         } else {
417                 PBD::warning << _("VST object file contains no plugins.") << endmsg;
418         }
419 }
420
421
422 /* *** CACHE MANAGEMENT *** */
423
424 /** remove info file from cache */
425 static void
426 vstfx_remove_infofile (const char *dllpath)
427 {
428         ::g_unlink (vstfx_infofile_path (dllpath).c_str ());
429 }
430
431 /** cache file for given plugin
432  * @return FILE of the .fsi cache if found and up-to-date*/
433 static FILE *
434 vstfx_infofile_for_read (const char* dllpath)
435 {
436         const size_t slen = strlen (dllpath);
437         if (
438                         (slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so"))
439                         &&
440                         (slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll"))
441            ) {
442                 return 0;
443         }
444
445         string const path = vstfx_infofile_path (dllpath);
446
447         if (Glib::file_test (path, Glib::FileTest (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR))) {
448                 GStatBuf dllstat;
449                 GStatBuf fsistat;
450
451                 if (g_stat (dllpath, &dllstat) == 0) {
452                         if (g_stat (path.c_str (), &fsistat) == 0) {
453                                 if (dllstat.st_mtime <= fsistat.st_mtime) {
454                                         /* plugin is older than info file */
455                                         return g_fopen (path.c_str (), "rb");
456                                 }
457                         }
458                 }
459                 PBD::warning << string_compose (_("Ignored VST plugin which is newer than cache: '%1' (cache: '%2')"), dllpath, path) << endmsg;
460                 PBD::info << _("Re-Scan Plugins (Preferences > Plugins) to update the cache, also make sure your system-time is set correctly.") << endmsg;
461         }
462         return NULL;
463 }
464
465 /** newly created cache file for given plugin
466  * @return FILE for the .fsi cache or NULL on error
467  */
468 static FILE *
469 vstfx_infofile_for_write (const char* dllpath)
470 {
471         const size_t slen = strlen (dllpath);
472         if (
473                         (slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so"))
474                         &&
475                         (slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll"))
476            ) {
477                 return NULL;
478         }
479
480         string const path = vstfx_infofile_path (dllpath);
481         return g_fopen (path.c_str (), "wb");
482 }
483
484 /** check if cache-file exists, is up-to-date and parse cache file
485  * @param infos [return] loaded plugin info
486  * @return true if .fsi cache was read successfully, false otherwise
487  */
488 static bool
489 vstfx_get_info_from_file (const char* dllpath, vector<VSTInfo*> *infos)
490 {
491         FILE* infofile;
492         bool rv = false;
493         if ((infofile = vstfx_infofile_for_read (dllpath)) != 0) {
494                 rv = vstfx_load_info_file (infofile, infos);
495                 fclose (infofile);
496                 if (!rv) {
497                         PBD::warning << string_compose (_("Cannot get VST information for '%1': failed to load cache file."), dllpath) << endmsg;
498                 }
499         }
500         return rv;
501 }
502
503
504
505 /* *** VST system-under-test methods *** */
506
507 static
508 bool vstfx_midi_input (VSTState* vstfx)
509 {
510         AEffect* plugin = vstfx->plugin;
511
512         int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, 0, 0.0f);
513
514         if (vst_version >= 2) {
515                 /* should we send it VST events (i.e. MIDI) */
516
517                 if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast<char*> ("receiveVstEvents"), 0.0f) > 0)) {
518                         return true;
519                 }
520         }
521
522         return false;
523 }
524
525 static
526 bool vstfx_midi_output (VSTState* vstfx)
527 {
528         AEffect* plugin = vstfx->plugin;
529
530         int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, 0, 0.0f);
531
532         if (vst_version >= 2) {
533                 /* should we send it VST events (i.e. MIDI) */
534
535                 if (   (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast<char*> ("sendVstEvents"), 0.0f) > 0)
536                     || (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast<char*> ("sendVstMidiEvent"), 0.0f) > 0)
537                    ) {
538                         return true;
539                 }
540         }
541
542         return false;
543 }
544
545 /** simple 'dummy' audiomaster callback to instantiate the plugin
546  * and query information
547  */
548 static intptr_t
549 simple_master_callback (AEffect *, int32_t opcode, int32_t, intptr_t, void *ptr, float)
550 {
551         const char* vstfx_can_do_strings[] = {
552                 "supplyIdle",
553                 "sendVstTimeInfo",
554                 "sendVstEvents",
555                 "sendVstMidiEvent",
556                 "receiveVstEvents",
557                 "receiveVstMidiEvent",
558                 "supportShell",
559                 "shellCategory",
560                 "shellCategorycurID"
561         };
562         const int vstfx_can_do_string_count = 9;
563
564         if (opcode == audioMasterVersion) {
565                 return 2400;
566         }
567         else if (opcode == audioMasterCanDo) {
568                 for (int i = 0; i < vstfx_can_do_string_count; i++) {
569                         if (! strcmp (vstfx_can_do_strings[i], (const char*)ptr)) {
570                                 return 1;
571                         }
572                 }
573                 return 0;
574         }
575         else if (opcode == audioMasterCurrentId) {
576                 return vstfx_current_loading_id;
577         }
578         else {
579                 return 0;
580         }
581 }
582
583
584 /** main plugin query and test function */
585 static VSTInfo*
586 vstfx_parse_vst_state (VSTState* vstfx)
587 {
588         assert (vstfx);
589
590         VSTInfo* info = (VSTInfo*) malloc (sizeof (VSTInfo));
591         if (!info) {
592                 return 0;
593         }
594
595         /* We need to init the creator because some plugins
596          * fail to implement getVendorString, and so won't stuff the
597          * string with any name */
598
599         char creator[65] = "Unknown";
600         char name[65] = "";
601
602         AEffect* plugin = vstfx->plugin;
603
604
605         plugin->dispatcher (plugin, effGetEffectName, 0, 0, name, 0);
606
607         if (strlen (name) == 0) {
608                 plugin->dispatcher (plugin, effGetProductString, 0, 0, name, 0);
609         }
610
611         if (strlen (name) == 0) {
612                 info->name = strdup (vstfx->handle->name);
613         } else {
614                 info->name = strdup (name);
615         }
616
617         /*If the plugin doesn't bother to implement GetVendorString we will
618          * have pre-stuffed the string with 'Unknown' */
619
620         plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
621
622         /* Some plugins DO implement GetVendorString, but DON'T put a name in it
623          * so if its just a zero length string we replace it with 'Unknown' */
624
625         if (strlen (creator) == 0) {
626                 info->creator = strdup ("Unknown");
627         } else {
628                 info->creator = strdup (creator);
629         }
630
631
632         switch (plugin->dispatcher (plugin, effGetPlugCategory, 0, 0, 0, 0))
633         {
634                 case kPlugCategEffect:         info->Category = strdup ("Effect"); break;
635                 case kPlugCategSynth:          info->Category = strdup ("Synth"); break;
636                 case kPlugCategAnalysis:       info->Category = strdup ("Anaylsis"); break;
637                 case kPlugCategMastering:      info->Category = strdup ("Mastering"); break;
638                 case kPlugCategSpacializer:    info->Category = strdup ("Spacializer"); break;
639                 case kPlugCategRoomFx:         info->Category = strdup ("RoomFx"); break;
640                 case kPlugSurroundFx:          info->Category = strdup ("SurroundFx"); break;
641                 case kPlugCategRestoration:    info->Category = strdup ("Restoration"); break;
642                 case kPlugCategOfflineProcess: info->Category = strdup ("Offline"); break;
643                 case kPlugCategShell:          info->Category = strdup ("Shell"); break;
644                 case kPlugCategGenerator:      info->Category = strdup ("Generator"); break;
645                 default:                       info->Category = strdup ("Unknown"); break;
646         }
647
648         info->UniqueID = plugin->uniqueID;
649
650         info->numInputs = plugin->numInputs;
651         info->numOutputs = plugin->numOutputs;
652         info->numParams = plugin->numParams;
653         info->wantMidi = (vstfx_midi_input (vstfx) ? 1 : 0) | (vstfx_midi_output (vstfx) ? 2 : 0);
654         info->hasEditor = plugin->flags & effFlagsHasEditor ? true : false;
655         info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? true : false;
656         info->ParamNames = (char **) malloc (sizeof (char*)*info->numParams);
657         info->ParamLabels = (char **) malloc (sizeof (char*)*info->numParams);
658
659         for (int i = 0; i < info->numParams; ++i) {
660                 char name[64];
661                 char label[64];
662
663                 /* Not all plugins give parameters labels as well as names */
664
665                 strcpy (name, "No Name");
666                 strcpy (label, "No Label");
667
668                 plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
669                 info->ParamNames[i] = strdup (name);
670
671                 //NOTE: 'effGetParamLabel' is no longer defined in vestige headers
672                 //plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
673                 info->ParamLabels[i] = strdup (label);
674         }
675         return info;
676 }
677
678 /** wrapper around \ref vstfx_parse_vst_state,
679  * iterate over plugins in shell, translate VST-info into ardour VSTState
680  */
681 static void
682 vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector<VSTInfo *> *infos, enum ARDOUR::PluginType type)
683 {
684         assert (vstfx);
685         VSTInfo *info;
686
687         if (!(info = vstfx_parse_vst_state (vstfx))) {
688                 return;
689         }
690
691         infos->push_back (info);
692 #if 1 // shell-plugin support
693         /* If this plugin is a Shell and we are not already inside a shell plugin
694          * read the info for all of the plugins contained in this shell.
695          */
696         if (!strncmp (info->Category, "Shell", 5)
697                         && vstfx->handle->plugincnt == 1) {
698                 int id;
699                 vector< pair<int, string> > ids;
700                 AEffect *plugin = vstfx->plugin;
701
702                 do {
703                         char name[65] = "Unknown";
704                         id = plugin->dispatcher (plugin, effShellGetNextPlugin, 0, 0, name, 0);
705                         ids.push_back (std::make_pair (id, name));
706                 } while ( id != 0 );
707
708                 switch (type) {
709 #ifdef WINDOWS_VST_SUPPORT
710                         case ARDOUR::Windows_VST:
711                                 fst_close (vstfx);
712                                 break;
713 #endif
714 #ifdef LXVST_SUPPORT
715                         case ARDOUR::LXVST:
716                                 vstfx_close (vstfx);
717                                 break;
718 #endif
719                         default:
720                                 assert (0);
721                                 break;
722                 }
723
724                 for (vector< pair<int, string> >::iterator x = ids.begin (); x != ids.end (); ++x) {
725                         id = (*x).first;
726                         if (id == 0) continue;
727                         /* recurse vstfx_get_info() */
728
729                         bool ok;
730                         switch (type) {
731 #ifdef WINDOWS_VST_SUPPORT
732                                 case ARDOUR::Windows_VST:
733                                         ok = vstfx_instantiate_and_get_info_fst (dllpath, infos, id);
734                                         break;
735 #endif
736 #ifdef LXVST_SUPPORT
737                                 case ARDOUR::LXVST:
738                                         ok = vstfx_instantiate_and_get_info_lx (dllpath, infos, id);
739                                         break;
740 #endif
741                                 default:
742                                         ok = false;
743                                         break;
744                         }
745                         if (ok) {
746                                 // One shell (some?, all?) does not report the actual plugin name
747                                 // even after the shelled plugin has been instantiated.
748                                 // Replace the name of the shell with the real name.
749                                 info = infos->back ();
750                                 free (info->name);
751
752                                 if ((*x).second.length () == 0) {
753                                         info->name = strdup ("Unknown");
754                                 }
755                                 else {
756                                         info->name = strdup ((*x).second.c_str ());
757                                 }
758                         }
759                 }
760         } else {
761                 switch (type) {
762 #ifdef WINDOWS_VST_SUPPORT
763                         case ARDOUR::Windows_VST:
764                                 fst_close (vstfx);
765                                 break;
766 #endif
767 #ifdef LXVST_SUPPORT
768                         case ARDOUR::LXVST:
769                                 vstfx_close (vstfx);
770                                 break;
771 #endif
772                         default:
773                                 assert (0);
774                                 break;
775                 }
776         }
777 #endif
778 }
779
780
781
782 /* *** TOP-LEVEL PLUGIN INSTANTIATION FUNCTIONS *** */
783
784 #ifdef LXVST_SUPPORT
785 static bool
786 vstfx_instantiate_and_get_info_lx (
787                 const char* dllpath, vector<VSTInfo*> *infos, int uniqueID)
788 {
789         VSTHandle* h;
790         VSTState* vstfx;
791         if (!(h = vstfx_load (dllpath))) {
792                 PBD::warning << string_compose (_("Cannot get LinuxVST information from '%1': load failed."), dllpath) << endmsg;
793                 return false;
794         }
795
796         vstfx_current_loading_id = uniqueID;
797
798         if (!(vstfx = vstfx_instantiate (h, simple_master_callback, 0))) {
799                 vstfx_unload (h);
800                 PBD::warning << string_compose (_("Cannot get LinuxVST information from '%1': instantiation failed."), dllpath) << endmsg;
801                 return false;
802         }
803
804         vstfx_current_loading_id = 0;
805
806         vstfx_info_from_plugin (dllpath, vstfx, infos, ARDOUR::LXVST);
807
808         vstfx_unload (h);
809         return true;
810 }
811 #endif
812
813 #ifdef WINDOWS_VST_SUPPORT
814 static bool
815 vstfx_instantiate_and_get_info_fst (
816                 const char* dllpath, vector<VSTInfo*> *infos, int uniqueID)
817 {
818         VSTHandle* h;
819         VSTState* vstfx;
820         if (!(h = fst_load (dllpath))) {
821                 PBD::warning << string_compose (_("Cannot get Windows VST information from '%1': load failed."), dllpath) << endmsg;
822                 return false;
823         }
824
825         vstfx_current_loading_id = uniqueID;
826
827         if (!(vstfx = fst_instantiate (h, simple_master_callback, 0))) {
828                 fst_unload (&h);
829                 vstfx_current_loading_id = 0;
830                 PBD::warning << string_compose (_("Cannot get Windows VST information from '%1': instantiation failed."), dllpath) << endmsg;
831                 return false;
832         }
833         vstfx_current_loading_id = 0;
834
835         vstfx_info_from_plugin (dllpath, vstfx, infos, ARDOUR::Windows_VST);
836
837         return true;
838 }
839 #endif
840
841
842
843 /* *** ERROR LOGGING *** */
844 #ifndef VST_SCANNER_APP
845
846 static FILE * _errorlog_fd = 0;
847 static char * _errorlog_dll = 0;
848
849 static void parse_scanner_output (std::string msg, size_t /*len*/)
850 {
851         if (!_errorlog_fd && !_errorlog_dll) {
852                 PBD::error << "VST scanner: " << msg;
853                 return;
854         }
855
856 #if 0 // TODO
857         if (!_errorlog_fd) {
858                 if (!(_errorlog_fd = g_fopen (vstfx_errorfile_path (_errorlog_dll).c_str (), "w"))) {
859                         PBD::error << "Cannot create plugin error-log for plugin " << _errorlog_dll;
860                         free (_errorlog_dll);
861                         _errorlog_dll = NULL;
862                 }
863         }
864 #endif
865
866         if (_errorlog_fd) {
867                 fprintf (_errorlog_fd, "%s\n", msg.c_str ());
868         } else if (_errorlog_dll) {
869                 PBD::error << "VST '" << _errorlog_dll << "': " << msg;
870         } else {
871                 PBD::error << "VST scanner: " << msg;
872         }
873 }
874
875 static void
876 set_error_log (const char* dllpath) {
877         assert (!_errorlog_fd);
878         assert (!_errorlog_dll);
879         _errorlog_dll = strdup (dllpath);
880 }
881
882 static void
883 close_error_log () {
884         if (_errorlog_fd) {
885                 fclose (_errorlog_fd);
886                 _errorlog_fd = 0;
887         }
888         free (_errorlog_dll);
889         _errorlog_dll = 0;
890 }
891
892 #endif
893
894
895 /* *** the main function that uses all of the above *** */
896
897 static vector<VSTInfo *> *
898 vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanMode mode)
899 {
900         FILE* infofile;
901         vector<VSTInfo*> *infos = new vector<VSTInfo*>;
902
903         if (vst_is_blacklisted (dllpath)) {
904                 return infos;
905         }
906
907         if (vstfx_get_info_from_file (dllpath, infos)) {
908                 return infos;
909         }
910
911 #ifndef VST_SCANNER_APP
912         std::string scanner_bin_path = ARDOUR::PluginManager::scanner_bin_path;
913
914         if (mode == VST_SCAN_CACHE_ONLY) {
915                 /* never scan explicitly, use cache only */
916                 return infos;
917         }
918         else if (mode == VST_SCAN_USE_APP && scanner_bin_path != "") {
919                 /* use external scanner app */
920
921                 char **argp= (char**) calloc (3,sizeof (char*));
922                 argp[0] = strdup (scanner_bin_path.c_str ());
923                 argp[1] = strdup (dllpath);
924                 argp[2] = 0;
925
926                 set_error_log (dllpath);
927                 ARDOUR::SystemExec scanner (scanner_bin_path, argp);
928                 PBD::ScopedConnectionList cons;
929                 scanner.ReadStdout.connect_same_thread (cons, boost::bind (&parse_scanner_output, _1 ,_2));
930                 if (scanner.start (2 /* send stderr&stdout via signal */)) {
931                         PBD::error << string_compose (_("Cannot launch VST scanner app '%1': %2"), scanner_bin_path, strerror (errno)) << endmsg;
932                         close_error_log ();
933                         return infos;
934                 } else {
935                         int timeout = PLUGIN_SCAN_TIMEOUT;
936                         bool no_timeout = (timeout <= 0);
937                         ARDOUR::PluginScanTimeout (timeout);
938                         while (scanner.is_running () && (no_timeout || timeout > 0)) {
939                                 if (!no_timeout && !ARDOUR::PluginManager::instance ().no_timeout ()) {
940                                         if (timeout%5 == 0) {
941                                                 ARDOUR::PluginScanTimeout (timeout);
942                                         }
943                                         --timeout;
944                                 }
945                                 ARDOUR::GUIIdle ();
946                                 Glib::usleep (100000);
947
948                                 if (ARDOUR::PluginManager::instance ().cancelled ()) {
949                                         // remove info file (might be incomplete)
950                                         vstfx_remove_infofile (dllpath);
951                                         // remove temporary blacklist file (scan incomplete)
952                                         vstfx_un_blacklist (dllpath);
953                                         scanner.terminate ();
954                                         close_error_log ();
955                                         return infos;
956                                 }
957                         }
958                         scanner.terminate ();
959                 }
960                 close_error_log ();
961                 /* re-read index (generated by external scanner) */
962                 vstfx_clear_info_list (infos);
963                 if (!vst_is_blacklisted (dllpath)) {
964                         vstfx_get_info_from_file (dllpath, infos);
965                 }
966                 return infos;
967         }
968         /* else .. instantiate and check in in ardour process itself */
969 #else
970         (void) mode; // unused parameter
971 #endif
972
973         bool ok;
974         /* blacklist in case instantiation fails */
975         vstfx_blacklist (dllpath);
976
977         switch (type) {
978 #ifdef WINDOWS_VST_SUPPORT
979                 case ARDOUR::Windows_VST:
980                         ok = vstfx_instantiate_and_get_info_fst (dllpath, infos, 0);
981                         break;
982 #endif
983 #ifdef LXVST_SUPPORT
984                 case ARDOUR::LXVST:
985                         ok = vstfx_instantiate_and_get_info_lx (dllpath, infos, 0);
986                         break;
987 #endif
988                 default:
989                         ok = false;
990                         break;
991         }
992
993         if (!ok) {
994                 return infos;
995         }
996
997         /* remove from blacklist */
998         vstfx_un_blacklist (dllpath);
999
1000         /* crate cache/whitelist */
1001         infofile = vstfx_infofile_for_write (dllpath);
1002         if (!infofile) {
1003                 PBD::warning << string_compose (_("Cannot cache VST information for '%1': cannot create cache file."), dllpath) << endmsg;
1004                 return infos;
1005         } else {
1006                 vstfx_write_info_file (infofile, infos);
1007                 fclose (infofile);
1008         }
1009         return infos;
1010 }
1011
1012
1013 /* *** public API *** */
1014
1015 void
1016 vstfx_free_info_list (vector<VSTInfo *> *infos)
1017 {
1018         for (vector<VSTInfo *>::iterator i = infos->begin (); i != infos->end (); ++i) {
1019                 vstfx_free_info (*i);
1020         }
1021         delete infos;
1022 }
1023
1024 #ifdef LXVST_SUPPORT
1025 vector<VSTInfo *> *
1026 vstfx_get_info_lx (char* dllpath, enum VSTScanMode mode)
1027 {
1028         return vstfx_get_info (dllpath, ARDOUR::LXVST, mode);
1029 }
1030 #endif
1031
1032 #ifdef WINDOWS_VST_SUPPORT
1033 vector<VSTInfo *> *
1034 vstfx_get_info_fst (char* dllpath, enum VSTScanMode mode)
1035 {
1036         return vstfx_get_info (dllpath, ARDOUR::Windows_VST, mode);
1037 }
1038 #endif
1039
1040 #ifndef VST_SCANNER_APP
1041 } // namespace
1042 #endif