plugin menu/manager patch from J. Abelardo Gutierrez
[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 #define __STDC_FORMAT_MACROS 1
25 #include <stdint.h>
26
27 #include <sys/types.h>
28 #include <cstdio>
29 #include <lrdf.h>
30 #include <dlfcn.h>
31 #include <cstdlib>
32 #include <fstream>
33
34 #ifdef VST_SUPPORT
35 #include <fst.h>
36 #include "pbd/basename.h"
37 #include <cstring>
38 #endif // VST_SUPPORT
39
40 #include <glibmm/miscutils.h>
41
42 #include "pbd/pathscanner.h"
43
44 #include "ardour/ladspa.h"
45 #include "ardour/session.h"
46 #include "ardour/plugin_manager.h"
47 #include "ardour/plugin.h"
48 #include "ardour/ladspa_plugin.h"
49 #include "ardour/filesystem_paths.h"
50
51 #ifdef HAVE_SLV2
52 #include <slv2/slv2.h>
53 #include "ardour/lv2_plugin.h"
54 #endif
55
56 #ifdef VST_SUPPORT
57 #include "ardour/vst_plugin.h"
58 #endif
59
60 #ifdef HAVE_AUDIOUNITS
61 #include "ardour/audio_unit.h"
62 #include <Carbon/Carbon.h>
63 #endif
64
65 #include "pbd/error.h"
66 #include "pbd/stl_delete.h"
67
68 #include "i18n.h"
69
70 using namespace ARDOUR;
71 using namespace PBD;
72 using namespace std;
73
74 PluginManager* PluginManager::_manager = 0;
75
76 PluginManager::PluginManager ()
77         : _vst_plugin_info(0)
78         , _ladspa_plugin_info(0)
79         , _lv2_plugin_info(0)
80         , _au_plugin_info(0)
81 {
82         char* s;
83         string lrdf_path;
84
85         load_statuses ();
86
87 #ifdef HAVE_AUDIOUNITS
88         ProcessSerialNumber psn = { 0, kCurrentProcess };
89         OSStatus returnCode = TransformProcessType(& psn, kProcessTransformToForegroundApplication);
90         if( returnCode != 0) {
91                 error << _("Cannot become GUI app") << endmsg;
92         }
93 #endif
94
95         if ((s = getenv ("LADSPA_RDF_PATH"))){
96                 lrdf_path = s;
97         }
98
99         if (lrdf_path.length() == 0) {
100                 lrdf_path = "/usr/local/share/ladspa/rdf:/usr/share/ladspa/rdf";
101         }
102
103         add_lrdf_data(lrdf_path);
104         add_ladspa_presets();
105 #ifdef VST_SUPPORT
106         if (Config->get_use_vst()) {
107                 add_vst_presets();
108         }
109 #endif /* VST_SUPPORT */
110
111         if ((s = getenv ("LADSPA_PATH"))) {
112                 ladspa_path = s;
113         }
114
115         if ((s = getenv ("VST_PATH"))) {
116                 vst_path = s;
117         } else if ((s = getenv ("VST_PLUGINS"))) {
118                 vst_path = s;
119         }
120
121         if (_manager == 0) {
122                 _manager = this;
123         }
124
125         /* the plugin manager is constructed too early to use Profile */
126
127         if (getenv ("ARDOUR_SAE")) {
128                 ladspa_plugin_whitelist.push_back (1203); // single band parametric
129                 ladspa_plugin_whitelist.push_back (1772); // caps compressor
130                 ladspa_plugin_whitelist.push_back (1913); // fast lookahead limiter
131                 ladspa_plugin_whitelist.push_back (1075); // simple RMS expander
132                 ladspa_plugin_whitelist.push_back (1061); // feedback delay line (max 5s)
133                 ladspa_plugin_whitelist.push_back (1216); // gverb
134                 ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
135         }
136
137 #ifdef HAVE_SLV2
138         _lv2_world = new LV2World();
139 #endif
140
141         BootMessage (_("Discovering Plugins"));
142 }
143
144 void
145 PluginManager::refresh ()
146 {
147         ladspa_refresh ();
148 #ifdef HAVE_SLV2
149         lv2_refresh ();
150 #endif
151 #ifdef VST_SUPPORT
152         if (Config->get_use_vst()) {
153                 vst_refresh ();
154         }
155 #endif // VST_SUPPORT
156 #ifdef HAVE_AUDIOUNITS
157         au_refresh ();
158 #endif
159 }
160
161 void
162 PluginManager::ladspa_refresh ()
163 {
164         if (_ladspa_plugin_info)
165                 _ladspa_plugin_info->clear ();
166         else
167                 _ladspa_plugin_info = new ARDOUR::PluginInfoList ();
168
169         static const char *standard_paths[] = {
170                 "/usr/local/lib64/ladspa",
171                 "/usr/local/lib/ladspa",
172                 "/usr/lib64/ladspa",
173                 "/usr/lib/ladspa",
174                 "/Library/Audio/Plug-Ins/LADSPA",
175                 ""
176         };
177
178         /* allow LADSPA_PATH to augment, not override standard locations */
179
180         /* Only add standard locations to ladspa_path if it doesn't
181          * already contain them. Check for trailing '/'s too.
182          */
183
184         int i;
185         for (i = 0; standard_paths[i][0]; i++) {
186                 size_t found = ladspa_path.find(standard_paths[i]);
187                 if (found != ladspa_path.npos) {
188                         switch (ladspa_path[found + strlen(standard_paths[i])]) {
189                                 case ':' :
190                                 case '\0':
191                                         continue;
192                                 case '/' :
193                                         if (ladspa_path[found + strlen(standard_paths[i]) + 1] == ':' ||
194                                             ladspa_path[found + strlen(standard_paths[i]) + 1] == '\0') {
195                                                 continue;
196                                         }
197                         }
198                 }
199                 if (!ladspa_path.empty())
200                         ladspa_path += ":";
201
202                 ladspa_path += standard_paths[i];
203
204         }
205
206         ladspa_discover_from_path (ladspa_path);
207 }
208
209
210 int
211 PluginManager::add_ladspa_directory (string path)
212 {
213         if (ladspa_discover_from_path (path) == 0) {
214                 ladspa_path += ':';
215                 ladspa_path += path;
216                 return 0;
217         }
218         return -1;
219 }
220
221 static bool ladspa_filter (const string& str, void */*arg*/)
222 {
223         /* Not a dotfile, has a prefix before a period, suffix is "so" */
224
225         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
226 }
227
228 int
229 PluginManager::ladspa_discover_from_path (string /*path*/)
230 {
231         PathScanner scanner;
232         vector<string *> *plugin_objects;
233         vector<string *>::iterator x;
234         int ret = 0;
235
236         plugin_objects = scanner (ladspa_path, ladspa_filter, 0, true, true);
237
238         if (plugin_objects) {
239                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
240                         ladspa_discover (**x);
241                 }
242         }
243
244         vector_delete (plugin_objects);
245         return ret;
246 }
247
248 static bool rdf_filter (const string &str, void* /*arg*/)
249 {
250         return str[0] != '.' &&
251                    ((str.find(".rdf")  == (str.length() - 4)) ||
252             (str.find(".rdfs") == (str.length() - 5)) ||
253                     (str.find(".n3")   == (str.length() - 3)) ||
254                     (str.find(".ttl")  == (str.length() - 4)));
255 }
256
257 void
258 PluginManager::add_ladspa_presets()
259 {
260         add_presets ("ladspa");
261 }
262
263 void
264 PluginManager::add_vst_presets()
265 {
266         add_presets ("vst");
267 }
268 void
269 PluginManager::add_presets(string domain)
270 {
271
272         PathScanner scanner;
273         vector<string *> *presets;
274         vector<string *>::iterator x;
275
276         char* envvar;
277         if ((envvar = getenv ("HOME")) == 0) {
278                 return;
279         }
280
281         string path = string_compose("%1/.%2/rdf", envvar, domain);
282         presets = scanner (path, rdf_filter, 0, true, true);
283
284         if (presets) {
285                 for (x = presets->begin(); x != presets->end (); ++x) {
286                         string file = "file:" + **x;
287                         if (lrdf_read_file(file.c_str())) {
288                                 warning << string_compose(_("Could not parse rdf file: %1"), *x) << endmsg;
289                         }
290                 }
291         }
292
293         vector_delete (presets);
294 }
295
296 void
297 PluginManager::add_lrdf_data (const string &path)
298 {
299         PathScanner scanner;
300         vector<string *>* rdf_files;
301         vector<string *>::iterator x;
302         string uri;
303
304         rdf_files = scanner (path, rdf_filter, 0, true, true);
305
306         if (rdf_files) {
307                 for (x = rdf_files->begin(); x != rdf_files->end (); ++x) {
308                         uri = "file://" + **x;
309
310                         if (lrdf_read_file(uri.c_str())) {
311                                 warning << "Could not parse rdf file: " << uri << endmsg;
312                         }
313                 }
314         }
315
316         vector_delete (rdf_files);
317 }
318
319 int
320 PluginManager::ladspa_discover (string path)
321 {
322         void *module;
323         const LADSPA_Descriptor *descriptor;
324         LADSPA_Descriptor_Function dfunc;
325         const char *errstr;
326
327         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
328                 error << string_compose(_("LADSPA: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
329                 return -1;
330         }
331
332         dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor");
333
334         if ((errstr = dlerror()) != 0) {
335                 error << string_compose(_("LADSPA: module \"%1\" has no descriptor function."), path) << endmsg;
336                 error << errstr << endmsg;
337                 dlclose (module);
338                 return -1;
339         }
340
341         for (uint32_t i = 0; ; ++i) {
342                 if ((descriptor = dfunc (i)) == 0) {
343                         break;
344                 }
345
346                 if (!ladspa_plugin_whitelist.empty()) {
347                         if (find (ladspa_plugin_whitelist.begin(), ladspa_plugin_whitelist.end(), descriptor->UniqueID) == ladspa_plugin_whitelist.end()) {
348                                 continue;
349                         }
350                 }
351
352                 PluginInfoPtr info(new LadspaPluginInfo);
353                 info->name = descriptor->Name;
354                 info->category = get_ladspa_category(descriptor->UniqueID);
355                 info->creator = descriptor->Maker;
356                 info->path = path;
357                 info->index = i;
358                 info->n_inputs = ChanCount();
359                 info->n_outputs = ChanCount();
360                 info->type = ARDOUR::LADSPA;
361
362                 char buf[32];
363                 snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
364                 info->unique_id = buf;
365
366                 for (uint32_t n=0; n < descriptor->PortCount; ++n) {
367                         if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
368                                 if ( LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[n]) ) {
369                                         info->n_inputs.set_audio(info->n_inputs.n_audio() + 1);
370                                 }
371                                 else if ( LADSPA_IS_PORT_OUTPUT (descriptor->PortDescriptors[n]) ) {
372                                         info->n_outputs.set_audio(info->n_outputs.n_audio() + 1);
373                                 }
374                         }
375                 }
376
377                 if(_ladspa_plugin_info->empty()){
378                         _ladspa_plugin_info->push_back (info);
379                 }
380
381                 //Ensure that the plugin is not already in the plugin list.
382
383                 bool found = false;
384
385                 for (PluginInfoList::const_iterator i = _ladspa_plugin_info->begin(); i != _ladspa_plugin_info->end(); ++i) {
386                         if(0 == info->unique_id.compare((*i)->unique_id)){
387                               found = true;
388                         }
389                 }
390
391                 if(!found){
392                     _ladspa_plugin_info->push_back (info);
393                 }
394         }
395
396 // GDB WILL NOT LIKE YOU IF YOU DO THIS
397 //      dlclose (module);
398
399         return 0;
400 }
401
402 string
403 PluginManager::get_ladspa_category (uint32_t plugin_id)
404 {
405         char buf[256];
406         lrdf_statement pattern;
407
408         snprintf(buf, sizeof(buf), "%s%" PRIu32, LADSPA_BASE, plugin_id);
409         pattern.subject = buf;
410         pattern.predicate = (char*)RDF_TYPE;
411         pattern.object = 0;
412         pattern.object_type = lrdf_uri;
413
414         lrdf_statement* matches1 = lrdf_matches (&pattern);
415
416         if (!matches1) {
417                 return "Unknown";
418         }
419
420         pattern.subject = matches1->object;
421         pattern.predicate = (char*)(LADSPA_BASE "hasLabel");
422         pattern.object = 0;
423         pattern.object_type = lrdf_literal;
424
425         lrdf_statement* matches2 = lrdf_matches (&pattern);
426         lrdf_free_statements(matches1);
427
428         if (!matches2) {
429                 return ("Unknown");
430         }
431
432         string label = matches2->object;
433         lrdf_free_statements(matches2);
434
435         return label;
436 }
437
438 #ifdef HAVE_SLV2
439 void
440 PluginManager::lv2_refresh ()
441 {
442         delete _lv2_plugin_info;
443         _lv2_plugin_info = LV2PluginInfo::discover(_lv2_world);
444 }
445 #endif
446
447 #ifdef HAVE_AUDIOUNITS
448 void
449 PluginManager::au_refresh ()
450 {
451         delete _au_plugin_info;
452         _au_plugin_info = AUPluginInfo::discover();
453 }
454
455 #endif
456
457 #ifdef VST_SUPPORT
458
459 void
460 PluginManager::vst_refresh ()
461 {
462         if (_vst_plugin_info)
463                 _vst_plugin_info->clear ();
464         else
465                 _vst_plugin_info = new ARDOUR::PluginInfoList();
466
467         if (vst_path.length() == 0) {
468                 vst_path = "/usr/local/lib/vst:/usr/lib/vst";
469         }
470
471         vst_discover_from_path (vst_path);
472 }
473
474 int
475 PluginManager::add_vst_directory (string path)
476 {
477         if (vst_discover_from_path (path) == 0) {
478                 vst_path += ':';
479                 vst_path += path;
480                 return 0;
481         }
482         return -1;
483 }
484
485 static bool vst_filter (const string& str, void *arg)
486 {
487         /* Not a dotfile, has a prefix before a period, suffix is "dll" */
488
489         return str[0] != '.' && (str.length() > 4 && str.find (".dll") == (str.length() - 4));
490 }
491
492 int
493 PluginManager::vst_discover_from_path (string path)
494 {
495         PathScanner scanner;
496         vector<string *> *plugin_objects;
497         vector<string *>::iterator x;
498         int ret = 0;
499
500         info << "detecting VST plugins along " << path << endmsg;
501
502         plugin_objects = scanner (vst_path, vst_filter, 0, true, true);
503
504         if (plugin_objects) {
505                 for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
506                         vst_discover (**x);
507                 }
508         }
509
510         vector_delete (plugin_objects);
511         return ret;
512 }
513
514 int
515 PluginManager::vst_discover (string path)
516 {
517         FSTInfo* finfo;
518         char buf[32];
519
520         if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
521                 warning << "Cannot get VST information from " << path << endmsg;
522                 return -1;
523         }
524
525         if (!finfo->canProcessReplacing) {
526                 warning << string_compose (_("VST plugin %1 does not support processReplacing, and so cannot be used in ardour at this time"),
527                                     finfo->name)
528                         << endl;
529         }
530
531         PluginInfoPtr info(new VSTPluginInfo);
532
533         /* what a joke freeware VST is */
534
535         if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
536                 info->name = PBD::basename_nosuffix (path);
537         } else {
538                 info->name = finfo->name;
539         }
540
541
542         snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
543         info->unique_id = buf;
544         info->category = "VST";
545         info->path = path;
546         info->creator = finfo->creator;
547         info->index = 0;
548         info->n_inputs.set_audio (finfo->numInputs);
549         info->n_outputs.set_audio (finfo->numOutputs);
550         info->type = ARDOUR::VST;
551
552         _vst_plugin_info->push_back (info);
553         fst_free_info (finfo);
554
555         return 0;
556 }
557
558 #endif // VST_SUPPORT
559
560 PluginManager::PluginStatusType
561 PluginManager::get_status (const PluginInfoPtr& pi)
562 {
563         PluginStatus ps (pi->type, pi->unique_id);
564         PluginStatusList::const_iterator i =  find (statuses.begin(), statuses.end(), ps);
565         if (i ==  statuses.end() ) {
566                 return Normal;
567         } else {
568                 return i->status;
569         }
570 }
571
572 void
573 PluginManager::save_statuses ()
574 {
575         ofstream ofs;
576         sys::path path = user_config_directory();
577         path /= "plugin_statuses";
578
579         ofs.open (path.to_string().c_str(), ios_base::openmode (ios::out|ios::trunc));
580
581         if (!ofs) {
582                 return;
583         }
584
585         for (PluginStatusList::iterator i = statuses.begin(); i != statuses.end(); ++i) {
586                 switch ((*i).type) {
587                 case LADSPA:
588                         ofs << "LADSPA";
589                         break;
590                 case AudioUnit:
591                         ofs << "AudioUnit";
592                         break;
593                 case LV2:
594                         ofs << "LV2";
595                         break;
596                 case VST:
597                         ofs << "VST";
598                         break;
599                 }
600
601                 ofs << ' ' << (*i).unique_id << ' ';
602
603                 switch ((*i).status) {
604                 case Normal:
605                         ofs << "Normal";
606                         break;
607                 case Favorite:
608                         ofs << "Favorite";
609                         break;
610                 case Hidden:
611                         ofs << "Hidden";
612                         break;
613                 }
614
615                 ofs << endl;
616         }
617
618         ofs.close ();
619 }
620
621 void
622 PluginManager::load_statuses ()
623 {
624         sys::path path = user_config_directory();
625         path /= "plugin_statuses";
626         ifstream ifs (path.to_string().c_str());
627
628         if (!ifs) {
629                 return;
630         }
631
632         std::string stype;
633         std::string id;
634         std::string sstatus;
635         PluginType type;
636         PluginStatusType status;
637
638         while (ifs) {
639
640                 ifs >> stype;
641                 if (!ifs) {
642                         break;
643
644                 }
645                 ifs >> id;
646                 if (!ifs) {
647                         break;
648                 }
649
650                 ifs >> sstatus;
651                 if (!ifs) {
652                         break;
653
654                 }
655
656                 if (stype == "LADSPA") {
657                         type = LADSPA;
658                 } else if (stype == "AudioUnit") {
659                         type = AudioUnit;
660                 } else if (stype == "LV2") {
661                         type = LV2;
662                 } else if (stype == "VST") {
663                         type = VST;
664                 } else {
665                         error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
666                               << endmsg;
667                         continue;
668                 }
669                 if (sstatus == "Normal") {
670                         status = Normal;
671                 } else if (sstatus == "Favorite") {
672                         status = Favorite;
673                 } else if (sstatus == "Hidden") {
674                         status = Hidden;
675                 } else {
676                         error << string_compose (_("unknown plugin status type \"%1\" - ignored"), stype)
677                               << endmsg;
678                         continue;
679                 }
680
681                 set_status (type, id, status);
682         }
683
684         ifs.close ();
685 }
686
687 void
688 PluginManager::set_status (PluginType t, string id, PluginStatusType status)
689 {
690         PluginStatus ps (t, id, status);
691         statuses.erase (ps);
692
693         if (status == Normal) {
694                 return;
695         }
696
697         pair<PluginStatusList::iterator, bool> res = statuses.insert (ps);
698         //cerr << "Added " << t << " " << id << " " << status << " success ? " << res.second << endl;
699 }
700
701 ARDOUR::PluginInfoList&
702 PluginManager::vst_plugin_info ()
703 {
704 #ifdef VST_SUPPORT
705         if (!_vst_plugin_info)
706                 vst_refresh();
707         return *_vst_plugin_info;
708 #else
709         return _empty_plugin_info;
710 #endif
711 }
712
713 ARDOUR::PluginInfoList&
714 PluginManager::ladspa_plugin_info ()
715 {
716         if (!_ladspa_plugin_info)
717                 ladspa_refresh();
718         return *_ladspa_plugin_info;
719 }
720
721 ARDOUR::PluginInfoList&
722 PluginManager::lv2_plugin_info ()
723 {
724 #ifdef HAVE_SLV2
725         if (!_lv2_plugin_info)
726                 lv2_refresh();
727         return *_lv2_plugin_info;
728 #else
729         return _empty_plugin_info;
730 #endif
731 }
732
733 ARDOUR::PluginInfoList&
734 PluginManager::au_plugin_info ()
735 {
736 #ifdef HAVE_AUDIOUNITS
737         if (!_au_plugin_info)
738                 au_refresh();
739         return *_au_plugin_info;
740 #else
741         return _empty_plugin_info;
742 #endif
743 }