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