Transfer 'vst_search_path()' into 'libs/ardour/search_paths.cc'
[ardour.git] / libs / ardour / plugin_manager.cc
1 /*
2     Copyright (C) 2000-2006 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 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <stdint.h>
25
26 #include <sys/types.h>
27 #include <cstdio>
28 #include <cstdlib>
29 #include <fstream>
30
31 #ifdef HAVE_LRDF
32 #include <lrdf.h>
33 #endif
34
35 #ifdef WINDOWS_VST_SUPPORT
36 #include "ardour/vst_info_file.h"
37 #include "fst.h"
38 #include "pbd/basename.h"
39 #include <cstring>
40 #endif // WINDOWS_VST_SUPPORT
41
42 #ifdef LXVST_SUPPORT
43 #include "ardour/vst_info_file.h"
44 #include "ardour/linux_vst_support.h"
45 #include "pbd/basename.h"
46 #include <cstring>
47 #endif //LXVST_SUPPORT
48
49 #include <glib/gstdio.h>
50 #include <glibmm/miscutils.h>
51 #include <glibmm/pattern.h>
52
53 #include "pbd/pathscanner.h"
54 #include "pbd/whitespace.h"
55 #include "pbd/file_utils.h"
56
57 #include "ardour/debug.h"
58 #include "ardour/filesystem_paths.h"
59 #include "ardour/ladspa.h"
60 #include "ardour/ladspa_plugin.h"
61 #include "ardour/plugin.h"
62 #include "ardour/plugin_manager.h"
63 #include "ardour/rc_configuration.h"
64
65 #include "ardour/search_paths.h"
66
67 #ifdef LV2_SUPPORT
68 #include "ardour/lv2_plugin.h"
69 #endif
70
71 #ifdef WINDOWS_VST_SUPPORT
72 #include "ardour/windows_vst_plugin.h"
73 #endif
74
75 #ifdef LXVST_SUPPORT
76 #include "ardour/lxvst_plugin.h"
77 #endif
78
79 #ifdef AUDIOUNIT_SUPPORT
80 #include "ardour/audio_unit.h"
81 #include <Carbon/Carbon.h>
82 #endif
83
84 #include "pbd/error.h"
85 #include "pbd/stl_delete.h"
86
87 #include "i18n.h"
88
89 #include "ardour/debug.h"
90
91 using namespace ARDOUR;
92 using namespace PBD;
93 using namespace std;
94
95 PluginManager* PluginManager::_instance = 0;
96 std::string PluginManager::scanner_bin_path = "";
97
98 PluginManager&
99 PluginManager::instance()
100 {
101         if (!_instance) {
102                 _instance = new PluginManager;
103         }
104         return *_instance;
105 }
106
107 PluginManager::PluginManager ()
108         : _windows_vst_plugin_info(0)
109         , _lxvst_plugin_info(0)
110         , _ladspa_plugin_info(0)
111         , _lv2_plugin_info(0)
112         , _au_plugin_info(0)
113         , _cancel_scan(false)
114         , _cancel_timeout(false)
115 {
116         char* s;
117         string lrdf_path;
118
119         if (!PBD::find_file_in_search_path (
120                                 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst")),
121                                 "ardour-vst-scanner", scanner_bin_path)) {
122                 PBD::warning << "VST scanner app not found.'" << endmsg;
123         }
124
125         load_statuses ();
126
127         if ((s = getenv ("LADSPA_RDF_PATH"))){
128                 lrdf_path = s;
129         }
130
131         if (lrdf_path.length() == 0) {
132                 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
133         }
134
135         add_lrdf_data(lrdf_path);
136         add_ladspa_presets();
137 #ifdef WINDOWS_VST_SUPPORT
138         if (Config->get_use_windows_vst ()) {
139                 add_windows_vst_presets ();
140         }
141 #endif /* WINDOWS_VST_SUPPORT */
142
143 #ifdef LXVST_SUPPORT
144         if (Config->get_use_lxvst()) {
145                 add_lxvst_presets();
146         }
147 #endif /* Native LinuxVST support*/
148
149         if ((s = getenv ("VST_PATH"))) {
150                 windows_vst_path = s;
151         } else if ((s = getenv ("VST_PLUGINS"))) {
152                 windows_vst_path = s;
153         }
154
155         if (windows_vst_path.length() == 0) {
156                 windows_vst_path = vst_search_path ();
157         }
158
159         if ((s = getenv ("LXVST_PATH"))) {
160                 lxvst_path = s;
161         } else if ((s = getenv ("LXVST_PLUGINS"))) {
162                 lxvst_path = s;
163         }
164
165         if (lxvst_path.length() == 0) {
166                 lxvst_path = "/usr/local/lib64/lxvst:/usr/local/lib/lxvst:/usr/lib64/lxvst:/usr/lib/lxvst:"
167                         "/usr/local/lib64/linux_vst:/usr/local/lib/linux_vst:/usr/lib64/linux_vst:/usr/lib/linux_vst:"
168                         "/usr/lib/vst:/usr/local/lib/vst";
169         }
170
171         /* first time setup, use 'default' path */
172         if (Config->get_plugin_path_lxvst() == X_("@default@")) {
173                 Config->set_plugin_path_lxvst(get_default_lxvst_path());
174         }
175         if (Config->get_plugin_path_vst() == X_("@default@")) {
176                 Config->set_plugin_path_vst(get_default_windows_vst_path());
177         }
178
179         if (_instance == 0) {
180                 _instance = this;
181         }
182
183         BootMessage (_("Discovering Plugins"));
184 }
185
186
187 PluginManager::~PluginManager()
188 {
189 }
190
191 void
192 PluginManager::refresh (bool cache_only)
193 {
194         DEBUG_TRACE (DEBUG::PluginManager, "PluginManager::refresh\n");
195         _cancel_scan = false;
196
197         BootMessage (_("Scanning LADSPA Plugins"));
198         ladspa_refresh ();
199 #ifdef LV2_SUPPORT
200         BootMessage (_("Scanning LV2 Plugins"));
201         lv2_refresh ();
202 #endif
203 #ifdef WINDOWS_VST_SUPPORT
204         if (Config->get_use_windows_vst()) {
205                 BootMessage (_("Scanning Windows VST Plugins"));
206                 windows_vst_refresh (cache_only);
207         }
208 #endif // WINDOWS_VST_SUPPORT
209
210 #ifdef LXVST_SUPPORT
211         if(Config->get_use_lxvst()) {
212                 BootMessage (_("Scanning Linux VST Plugins"));
213                 lxvst_refresh(cache_only);
214         }
215 #endif //Native linuxVST SUPPORT
216
217 #ifdef AUDIOUNIT_SUPPORT
218         BootMessage (_("Scanning AU Plugins"));
219         au_refresh ();
220 #endif
221
222         BootMessage (_("Plugin Scan Complete..."));
223         PluginListChanged (); /* EMIT SIGNAL */
224         PluginScanMessage(X_("closeme"), "", false);
225         _cancel_scan = false;
226 }
227
228 void
229 PluginManager::cancel_plugin_scan ()
230 {
231         _cancel_scan = true;
232 }
233
234 void
235 PluginManager::cancel_plugin_timeout ()
236 {
237         _cancel_timeout = true;
238 }
239
240 void
241 PluginManager::clear_vst_cache ()
242 {
243         // see also libs/ardour/vst_info_file.cc - vstfx_infofile_path()
244 #ifdef WINDOWS_VST_SUPPORT
245         {
246                 PathScanner scanner;
247                 vector<string *> *fsi_files;
248
249                 fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsi$", true, true, -1, false);
250                 if (fsi_files) {
251                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
252                                 ::g_unlink((*i)->c_str());
253                         }
254                 }
255                 vector_delete(fsi_files);
256         }
257 #endif
258
259 #ifdef LXVST_SUPPORT
260         {
261                 PathScanner scanner;
262                 vector<string *> *fsi_files;
263                 fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsi$", true, true, -1, false);
264                 if (fsi_files) {
265                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
266                                 ::g_unlink((*i)->c_str());
267                         }
268                 }
269                 vector_delete(fsi_files);
270         }
271 #endif
272
273 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
274         {
275                 string personal = get_personal_vst_info_cache_dir();
276                 PathScanner scanner;
277                 vector<string *> *fsi_files;
278                 fsi_files = scanner (personal, "\\.fsi$", true, true, -1, false);
279                 if (fsi_files) {
280                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
281                                 ::g_unlink((*i)->c_str());
282                         }
283                 }
284                 vector_delete(fsi_files);
285         }
286 #endif
287 }
288
289 void
290 PluginManager::clear_vst_blacklist ()
291 {
292 #ifdef WINDOWS_VST_SUPPORT
293         {
294                 PathScanner scanner;
295                 vector<string *> *fsi_files;
296
297                 fsi_files = scanner (Config->get_plugin_path_vst(), "\\.fsb$", true, true, -1, false);
298                 if (fsi_files) {
299                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
300                                 ::g_unlink((*i)->c_str());
301                         }
302                 }
303                 vector_delete(fsi_files);
304         }
305 #endif
306
307 #ifdef LXVST_SUPPORT
308         {
309                 PathScanner scanner;
310                 vector<string *> *fsi_files;
311                 fsi_files = scanner (Config->get_plugin_path_lxvst(), "\\.fsb$", true, true, -1, false);
312                 if (fsi_files) {
313                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
314                                 ::g_unlink((*i)->c_str());
315                         }
316                 }
317                 vector_delete(fsi_files);
318         }
319 #endif
320
321 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
322         {
323                 string personal = get_personal_vst_blacklist_dir();
324
325                 PathScanner scanner;
326                 vector<string *> *fsi_files;
327                 fsi_files = scanner (personal, "\\.fsb$", true, true, -1, false);
328                 if (fsi_files) {
329                         for (vector<string *>::iterator i = fsi_files->begin(); i != fsi_files->end (); ++i) {
330                                 ::g_unlink((*i)->c_str());
331                         }
332                 }
333                 vector_delete(fsi_files);
334         }
335 #endif
336 }
337
338 void
339 PluginManager::ladspa_refresh ()
340 {
341         if (_ladspa_plugin_info) {
342                 _ladspa_plugin_info->clear ();
343         } else {
344                 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
345         }
346
347         /* allow LADSPA_PATH to augment, not override standard locations */
348
349         /* Only add standard locations to ladspa_path if it doesn't
350          * already contain them. Check for trailing G_DIR_SEPARATOR too.
351          */
352
353         vector<string> ladspa_modules;
354
355         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA: search along: [%1]\n", ladspa_search_path().to_string()));
356
357         Glib::PatternSpec so_extension_pattern("*.so");
358         Glib::PatternSpec dylib_extension_pattern("*.dylib");
359         Glib::PatternSpec dll_extension_pattern("*.dll");
360
361         find_matching_files_in_search_path (ladspa_search_path (),
362                                             so_extension_pattern, ladspa_modules);
363
364         find_matching_files_in_search_path (ladspa_search_path (),
365                                             dylib_extension_pattern, ladspa_modules);
366
367         find_matching_files_in_search_path (ladspa_search_path (),
368                                             dll_extension_pattern, ladspa_modules);
369
370         for (vector<std::string>::iterator i = ladspa_modules.begin(); i != ladspa_modules.end(); ++i) {
371                 ARDOUR::PluginScanMessage(_("LADSPA"), *i, false);
372                 ladspa_discover (*i);
373         }
374 }
375
376 static bool rdf_filter (const string &str, void* /*arg*/)
377 {
378         return str[0] != '.' &&
379                    ((str.find(".rdf")  == (str.length() - 4)) ||
380             (str.find(".rdfs") == (str.length() - 5)) ||
381                     (str.find(".n3")   == (str.length() - 3)) ||
382                     (str.find(".ttl")  == (str.length() - 4)));
383 }
384
385 void
386 PluginManager::add_ladspa_presets()
387 {
388         add_presets ("ladspa");
389 }
390
391 void
392 PluginManager::add_windows_vst_presets()
393 {
394         add_presets ("windows-vst");
395 }
396
397 void
398 PluginManager::add_lxvst_presets()
399 {
400         add_presets ("lxvst");
401 }
402
403 void
404 PluginManager::add_presets(string domain)
405 {
406 #ifdef HAVE_LRDF
407         PathScanner scanner;
408         vector<string *> *presets;
409         vector<string *>::iterator x;
410
411         char* envvar;
412         if ((envvar = getenv ("HOME")) == 0) {
413                 return;
414         }
415
416         string path = string_compose("%1/.%2/rdf", envvar, domain);
417         presets = scanner (path, rdf_filter, 0, false, true);
418
419         if (presets) {
420                 for (x = presets->begin(); x != presets->end (); ++x) {
421                         string file = "file:" + **x;
422                         if (lrdf_read_file(file.c_str())) {
423                                 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
424                         }
425                 }
426
427                 vector_delete (presets);
428         }
429 #endif
430 }
431
432 void
433 PluginManager::add_lrdf_data (const string &path)
434 {
435 #ifdef HAVE_LRDF
436         PathScanner scanner;
437         vector<string *>* rdf_files;
438         vector<string *>::iterator x;
439
440         rdf_files = scanner (path, rdf_filter, 0, false, true);
441
442         if (rdf_files) {
443                 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
444                         const string uri(string("file://") + **x);
445
446                         if (lrdf_read_file(uri.c_str())) {
447                                 warning << "Could not parse rdf file: " << uri << endmsg;
448                         }
449                 }
450
451                 vector_delete (rdf_files);
452         }
453 #endif
454 }
455
456 int
457 PluginManager::ladspa_discover (string path)
458 {
459         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Checking for LADSPA plugin at %1\n", path));
460
461         Glib::Module module(path);
462         const LADSPA_Descriptor *descriptor;
463         LADSPA_Descriptor_Function dfunc;
464         void* func = 0;
465
466         if (!module) {
467                 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"),
468                         path, Glib::Module::get_last_error()) << endmsg;
469                 return -1;
470         }
471
472
473         if (!module.get_symbol("ladspa_descriptor", func)) {
474                 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
475                 error << Glib::Module::get_last_error() << endmsg;
476                 return -1;
477         }
478
479         dfunc = (LADSPA_Descriptor_Function)func;
480
481         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("LADSPA plugin found at %1\n", path));
482
483         for (uint32_t i = 0; ; ++i) {
484                 if ((descriptor = dfunc (i)) == 0) {
485                         break;
486                 }
487
488                 if (!ladspa_plugin_whitelist.empty()) {
489                         if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
490                                 continue;
491                         }
492                 }
493
494                 PluginInfoPtr info(new LadspaPluginInfo);
495                 info->name = descriptor->Name;
496                 info->category = get_ladspa_category(descriptor->UniqueID);
497                 info->creator = descriptor->Maker;
498                 info->path = path;
499                 info->index = i;
500                 info->n_inputs = ChanCount();
501                 info->n_outputs = ChanCount();
502                 info->type = ARDOUR::LADSPA;
503
504                 char buf[32];
505                 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
506                 info->unique_id = buf;
507
508                 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
509                         if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
510                                 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
511                                         info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
512                                 }
513                                 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
514                                         info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
515                                 }
516                         }
517                 }
518
519                 if(_ladspa_plugin_info->empty()){
520                         _ladspa_plugin_info->push_back (info);
521                 }
522
523                 //Ensure that the plugin is not already in the plugin list.
524
525                 bool found = false;
526
527                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
528                         if(0 == info->unique_id.compare((*i)->unique_id)){
529                               found = true;
530                         }
531                 }
532
533                 if(!found){
534                     _ladspa_plugin_info->push_back (info);
535                 }
536
537                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Found LADSPA plugin, name: %1, Inputs: %2, Outputs: %3\n", info->name, info->n_inputs, info->n_outputs));
538         }
539
540 // GDB WILL NOT LIKE YOU IF YOU DO THIS
541 //      dlclose (module);
542
543         return 0;
544 }
545
546 string
547 PluginManager::get_ladspa_category (uint32_t plugin_id)
548 {
549 #ifdef HAVE_LRDF
550         char buf[256];
551         lrdf_statement pattern;
552
553         snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
554         pattern.subject = buf;
555         pattern.predicate = const_cast<char*>(RDF_TYPE);
556         pattern.object = 0;
557         pattern.object_type = lrdf_uri;
558
559         lrdf_statement* matches1 = lrdf_matches (&pattern);
560
561         if (!matches1) {
562                 return "Unknown";
563         }
564
565         pattern.subject = matches1->object;
566         pattern.predicate = const_cast<char*>(LADSPA_BASE "hasLabel");
567         pattern.object = 0;
568         pattern.object_type = lrdf_literal;
569
570         lrdf_statement* matches2 = lrdf_matches (&pattern);
571         lrdf_free_statements(matches1);
572
573         if (!matches2) {
574                 return ("Unknown");
575         }
576
577         string label = matches2->object;
578         lrdf_free_statements(matches2);
579
580         /* Kludge LADSPA class names to be singular and match LV2 class names.
581            This avoids duplicate plugin menus for every class, which is necessary
582            to make the plugin category menu at all usable, but is obviously a
583            filthy kludge.
584
585            In the short term, lrdf could be updated so the labels match and a new
586            release made. To support both specs, we should probably be mapping the
587            URIs to the same category in code and perhaps tweaking that hierarchy
588            dynamically to suit the user. Personally, I (drobilla) think that time
589            is better spent replacing the little-used LRDF.
590
591            In the longer term, we will abandon LRDF entirely in favour of LV2 and
592            use that class hierarchy. Aside from fixing this problem properly, that
593            will also allow for translated labels. SWH plugins have been LV2 for
594            ages; TAP needs porting. I don't know of anything else with LRDF data.
595         */
596         if (label == "Utilities") {
597                 return "Utility";
598         } else if (label == "Pitch shifters") {
599                 return "Pitch Shifter";
600         } else if (label != "Dynamics" && label != "Chorus"
601                    &&label[label.length() - 1] == 's'
602                    && label[label.length() - 2] != 's') {
603                 return label.substr(0, label.length() - 1);
604         } else {
605                 return label;
606         }
607 #else
608                 return ("Unknown");
609 #endif
610 }
611
612 #ifdef LV2_SUPPORT
613 void
614 PluginManager::lv2_refresh ()
615 {
616         DEBUG_TRACE (DEBUG::PluginManager, "LV2: refresh\n");
617         delete _lv2_plugin_info;
618         _lv2_plugin_info = LV2PluginInfo::discover();
619 }
620 #endif
621
622 #ifdef AUDIOUNIT_SUPPORT
623 void
624 PluginManager::au_refresh ()
625 {
626         DEBUG_TRACE (DEBUG::PluginManager, "AU: refresh\n");
627         delete _au_plugin_info;
628         _au_plugin_info = AUPluginInfo::discover();
629 }
630
631 #endif
632
633 #ifdef WINDOWS_VST_SUPPORT
634
635 void
636 PluginManager::windows_vst_refresh (bool cache_only)
637 {
638         if (_windows_vst_plugin_info) {
639                 _windows_vst_plugin_info->clear ();
640         } else {
641                 _windows_vst_plugin_info = new ARDOUR::PluginInfoList();
642         }
643
644         windows_vst_discover_from_path (Config->get_plugin_path_vst(), cache_only);
645 }
646
647 static bool windows_vst_filter (const string& str, void * /*arg*/)
648 {
649         /* Not a dotfile, has a prefix before a period, suffix is "dll" */
650
651         return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
652 }
653
654 int
655 PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
656 {
657         PathScanner scanner;
658         vector<string *> *plugin_objects;
659         vector<string *>::iterator x;
660         int ret = 0;
661
662         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("detecting Windows VST plugins along %1\n", path));
663
664         plugin_objects = scanner (Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true);
665
666         if (plugin_objects) {
667                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
668                         ARDOUR::PluginScanMessage(_("VST"), **x, !cache_only && !cancelled());
669                         windows_vst_discover (**x, cache_only || cancelled());
670                 }
671
672                 vector_delete (plugin_objects);
673         }
674
675         return ret;
676 }
677
678 int
679 PluginManager::windows_vst_discover (string path, bool cache_only)
680 {
681         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("windows_vst_discover '%1'\n", path));
682
683         _cancel_timeout = false;
684         vector<VSTInfo*> * finfos = vstfx_get_info_fst (const_cast<char *> (path.c_str()),
685                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
686
687         if (finfos->empty()) {
688                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Windows VST information from '%1'\n", path));
689                 return -1;
690         }
691
692         uint32_t discovered = 0;
693         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
694                 VSTInfo* finfo = *x;
695                 char buf[32];
696
697                 if (!finfo->canProcessReplacing) {
698                         warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
699                                                          finfo->name, PROGRAM_NAME)
700                                 << endl;
701                         continue;
702                 }
703
704                 PluginInfoPtr info (new WindowsVSTPluginInfo);
705
706                 /* what a joke freeware VST is */
707
708                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
709                         info->name = PBD::basename_nosuffix (path);
710                 } else {
711                         info->name = finfo->name;
712                 }
713
714
715                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
716                 info->unique_id = buf;
717                 info->category = "VST";
718                 info->path = path;
719                 info->creator = finfo->creator;
720                 info->index = 0;
721                 info->n_inputs.set_audio (finfo->numInputs);
722                 info->n_outputs.set_audio (finfo->numOutputs);
723                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
724                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
725                 info->type = ARDOUR::Windows_VST;
726
727                 // TODO: check dup-IDs (lxvst AND windows vst)
728                 bool duplicate = false;
729
730                 if (!_windows_vst_plugin_info->empty()) {
731                         for (PluginInfoList::iterator i =_windows_vst_plugin_info->begin(); i != _windows_vst_plugin_info->end(); ++i) {
732                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
733                                         warning << "Ignoring duplicate Windows VST plugin " << info->name << "\n";
734                                         duplicate = true;
735                                         break;
736                                 }
737                         }
738                 }
739
740                 if (!duplicate) {
741                         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Windows VST plugin ID '%1'\n", info->unique_id));
742                         _windows_vst_plugin_info->push_back (info);
743                         discovered++;
744                 }
745         }
746
747         vstfx_free_info_list (finfos);
748         return discovered > 0 ? 0 : -1;
749 }
750
751 #endif // WINDOWS_VST_SUPPORT
752
753 #ifdef LXVST_SUPPORT
754
755 void
756 PluginManager::lxvst_refresh (bool cache_only)
757 {
758         if (_lxvst_plugin_info) {
759                 _lxvst_plugin_info->clear ();
760         } else {
761                 _lxvst_plugin_info = new ARDOUR::PluginInfoList();
762         }
763
764         lxvst_discover_from_path (Config->get_plugin_path_lxvst(), cache_only);
765 }
766
767 static bool lxvst_filter (const string& str, void *)
768 {
769         /* Not a dotfile, has a prefix before a period, suffix is "so" */
770
771         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
772 }
773
774 int
775 PluginManager::lxvst_discover_from_path (string path, bool cache_only)
776 {
777         PathScanner scanner;
778         vector<string *> *plugin_objects;
779         vector<string *>::iterator x;
780         int ret = 0;
781
782 #ifndef NDEBUG
783         (void) path;
784 #endif
785
786         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Discovering linuxVST plugins along %1\n", path));
787
788         plugin_objects = scanner (Config->get_plugin_path_lxvst(), lxvst_filter, 0, false, true);
789
790         if (plugin_objects) {
791                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
792                         ARDOUR::PluginScanMessage(_("LXVST"), **x, !cache_only && !cancelled());
793                         lxvst_discover (**x, cache_only || cancelled());
794                 }
795
796                 vector_delete (plugin_objects);
797         }
798
799         return ret;
800 }
801
802 int
803 PluginManager::lxvst_discover (string path, bool cache_only)
804 {
805         DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent LXVST plugin at %1\n", path));
806
807         _cancel_timeout = false;
808         vector<VSTInfo*> * finfos = vstfx_get_info_lx (const_cast<char *> (path.c_str()),
809                         cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
810
811         if (finfos->empty()) {
812                 DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Linux VST information from '%1'\n", path));
813                 return -1;
814         }
815
816         uint32_t discovered = 0;
817         for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
818                 VSTInfo* finfo = *x;
819                 char buf[32];
820
821                 if (!finfo->canProcessReplacing) {
822                         warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
823                                                          finfo->name, PROGRAM_NAME)
824                                 << endl;
825                         continue;
826                 }
827
828                 PluginInfoPtr info(new LXVSTPluginInfo);
829
830                 if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
831                         info->name = PBD::basename_nosuffix (path);
832                 } else {
833                         info->name = finfo->name;
834                 }
835
836
837                 snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
838                 info->unique_id = buf;
839                 info->category = "linuxVSTs";
840                 info->path = path;
841                 info->creator = finfo->creator;
842                 info->index = 0;
843                 info->n_inputs.set_audio (finfo->numInputs);
844                 info->n_outputs.set_audio (finfo->numOutputs);
845                 info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
846                 info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
847                 info->type = ARDOUR::LXVST;
848
849                                         /* Make sure we don't find the same plugin in more than one place along
850                          the LXVST_PATH We can't use a simple 'find' because the path is included
851                          in the PluginInfo, and that is the one thing we can be sure MUST be
852                          different if a duplicate instance is found.  So we just compare the type
853                          and unique ID (which for some VSTs isn't actually unique...)
854                 */
855
856                 // TODO: check dup-IDs with windowsVST, too
857                 bool duplicate = false;
858                 if (!_lxvst_plugin_info->empty()) {
859                         for (PluginInfoList::iterator i =_lxvst_plugin_info->begin(); i != _lxvst_plugin_info->end(); ++i) {
860                                 if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
861                                         warning << "Ignoring duplicate Linux VST plugin " << info->name << "\n";
862                                         duplicate = true;
863                                         break;
864                                 }
865                         }
866                 }
867
868                 if (!duplicate) {
869                         _lxvst_plugin_info->push_back (info);
870                         discovered++;
871                 }
872         }
873
874         vstfx_free_info_list (finfos);
875         return discovered > 0 ? 0 : -1;
876 }
877
878 #endif // LXVST_SUPPORT
879
880
881 PluginManager::PluginStatusType
882 PluginManager::get_status (const PluginInfoPtr& pi)
883 {
884         PluginStatus ps (pi->type, pi->unique_id);
885         PluginStatusList::const_iterator i =  find (statuses.begin(), statuses.end(), ps);
886         if (i ==  statuses.end() ) {
887                 return Normal;
888         } else {
889                 return i->status;
890         }
891 }
892
893 void
894 PluginManager::save_statuses ()
895 {
896         ofstream ofs;
897         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
898
899         ofs.open (path.c_str(), ios_base::openmode (ios::out|ios::trunc));
900
901         if (!ofs) {
902                 return;
903         }
904
905         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
906                 switch ((*i).type) {
907                 case LADSPA:
908                         ofs << "LADSPA";
909                         break;
910                 case AudioUnit:
911                         ofs << "AudioUnit";
912                         break;
913                 case LV2:
914                         ofs << "LV2";
915                         break;
916                 case Windows_VST:
917                         ofs << "Windows-VST";
918                         break;
919                 case LXVST:
920                         ofs << "LXVST";
921                         break;
922                 }
923
924                 ofs << ' ';
925
926                 switch ((*i).status) {
927                 case Normal:
928                         ofs << "Normal";
929                         break;
930                 case Favorite:
931                         ofs << "Favorite";
932                         break;
933                 case Hidden:
934                         ofs << "Hidden";
935                         break;
936                 }
937
938                 ofs << ' ';
939                 ofs << (*i).unique_id;;
940                 ofs << endl;
941         }
942
943         ofs.close ();
944 }
945
946 void
947 PluginManager::load_statuses ()
948 {
949         std::string path = Glib::build_filename (user_config_directory(), "plugin_statuses");
950         ifstream ifs (path.c_str());
951
952         if (!ifs) {
953                 return;
954         }
955
956         std::string stype;
957         std::string sstatus;
958         std::string id;
959         PluginType type;
960         PluginStatusType status;
961         char buf[1024];
962
963         while (ifs) {
964
965                 ifs >> stype;
966                 if (!ifs) {
967                         break;
968
969                 }
970
971                 ifs >> sstatus;
972                 if (!ifs) {
973                         break;
974
975                 }
976
977                 /* rest of the line is the plugin ID */
978
979                 ifs.getline (buf, sizeof (buf), '\n');
980                 if (!ifs) {
981                         break;
982                 }
983
984                 if (sstatus == "Normal") {
985                         status = Normal;
986                 } else if (sstatus == "Favorite") {
987                         status = Favorite;
988                 } else if (sstatus == "Hidden") {
989                         status = Hidden;
990                 } else {
991                         error << string_compose (_("unknown plugin status type \"%1\" - all entries ignored"), sstatus)
992                                   << endmsg;
993                         statuses.clear ();
994                         break;
995                 }
996
997                 if (stype == "LADSPA") {
998                         type = LADSPA;
999                 } else if (stype == "AudioUnit") {
1000                         type = AudioUnit;
1001                 } else if (stype == "LV2") {
1002                         type = LV2;
1003                 } else if (stype == "Windows-VST") {
1004                         type = Windows_VST;
1005                 } else if (stype == "LXVST") {
1006                         type = LXVST;
1007                 } else {
1008                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
1009                               << endmsg;
1010                         continue;
1011                 }
1012
1013                 id = buf;
1014                 strip_whitespace_edges (id);
1015                 set_status (type, id, status);
1016         }
1017
1018         ifs.close ();
1019 }
1020
1021 void
1022 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
1023 {
1024         PluginStatus ps (t, id, status);
1025         statuses.erase (ps);
1026
1027         if (status == Normal) {
1028                 return;
1029         }
1030
1031         statuses.insert (ps);
1032 }
1033
1034 ARDOUR::PluginInfoList&
1035 PluginManager::windows_vst_plugin_info ()
1036 {
1037 #ifdef WINDOWS_VST_SUPPORT
1038         if (!_windows_vst_plugin_info) {
1039                 windows_vst_refresh ();
1040         }
1041         return *_windows_vst_plugin_info;
1042 #else
1043         return _empty_plugin_info;
1044 #endif
1045 }
1046
1047 ARDOUR::PluginInfoList&
1048 PluginManager::lxvst_plugin_info ()
1049 {
1050 #ifdef LXVST_SUPPORT
1051         assert(_lxvst_plugin_info);
1052         return *_lxvst_plugin_info;
1053 #else
1054         return _empty_plugin_info;
1055 #endif
1056 }
1057
1058 ARDOUR::PluginInfoList&
1059 PluginManager::ladspa_plugin_info ()
1060 {
1061         assert(_ladspa_plugin_info);
1062         return *_ladspa_plugin_info;
1063 }
1064
1065 ARDOUR::PluginInfoList&
1066 PluginManager::lv2_plugin_info ()
1067 {
1068 #ifdef LV2_SUPPORT
1069         assert(_lv2_plugin_info);
1070         return *_lv2_plugin_info;
1071 #else
1072         return _empty_plugin_info;
1073 #endif
1074 }
1075
1076 ARDOUR::PluginInfoList&
1077 PluginManager::au_plugin_info ()
1078 {
1079 #ifdef AUDIOUNIT_SUPPORT
1080         assert(_au_plugin_info);
1081         return *_au_plugin_info;
1082 #else
1083         return _empty_plugin_info;
1084 #endif
1085 }