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