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