enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / ardour / ladspa_plugin.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 <inttypes.h>
25
26 #include <vector>
27 #include <string>
28
29 #include <cstdlib>
30 #include <cstdio> // so libraptor doesn't complain
31 #include <cmath>
32 #ifndef COMPILER_MSVC
33 #include <dirent.h>
34 #endif
35 #include <sys/stat.h>
36 #include <cerrno>
37
38 #ifdef HAVE_LRDF
39 #include <lrdf.h>
40 #endif
41
42 #include "pbd/compose.h"
43 #include "pbd/error.h"
44 #include "pbd/xml++.h"
45 #include "pbd/stacktrace.h"
46
47 #include "ardour/session.h"
48 #include "ardour/ladspa_plugin.h"
49 #include "ardour/buffer_set.h"
50 #include "ardour/audio_buffer.h"
51
52 #include "pbd/stl_delete.h"
53
54 #include "pbd/i18n.h"
55 #include <locale.h>
56
57 using namespace std;
58 using namespace ARDOUR;
59 using namespace PBD;
60
61 LadspaPlugin::LadspaPlugin (string module_path, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate)
62         : Plugin (e, session)
63 {
64         init (module_path, index, rate);
65 }
66
67 LadspaPlugin::LadspaPlugin (const LadspaPlugin &other)
68         : Plugin (other)
69 {
70         init (other._module_path, other._index, other._sample_rate);
71
72         for (uint32_t i = 0; i < parameter_count(); ++i) {
73                 _control_data[i] = other._shadow_data[i];
74                 _shadow_data[i] = other._shadow_data[i];
75         }
76 }
77
78 void
79 LadspaPlugin::init (string module_path, uint32_t index, framecnt_t rate)
80 {
81         void* func;
82         LADSPA_Descriptor_Function dfunc;
83         uint32_t i, port_cnt;
84
85         _module_path = module_path;
86         _module = new Glib::Module(_module_path);
87         _control_data = 0;
88         _shadow_data = 0;
89         _latency_control_port = 0;
90         _was_activated = false;
91
92         if (!(*_module)) {
93                 error << _("LADSPA: Unable to open module: ") << Glib::Module::get_last_error() << endmsg;
94                 delete _module;
95                 throw failed_constructor();
96         }
97
98         if (!_module->get_symbol("ladspa_descriptor", func)) {
99                 error << _("LADSPA: module has no descriptor function.") << endmsg;
100                 throw failed_constructor();
101         }
102
103         dfunc = (LADSPA_Descriptor_Function)func;
104
105         if ((_descriptor = dfunc (index)) == 0) {
106                 error << _("LADSPA: plugin has gone away since discovery!") << endmsg;
107                 throw failed_constructor();
108         }
109
110         _index = index;
111
112         if (LADSPA_IS_INPLACE_BROKEN(_descriptor->Properties)) {
113                 error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), _descriptor->Name) << endmsg;
114                 throw failed_constructor();
115         }
116
117         _sample_rate = rate;
118
119         if (_descriptor->instantiate == 0) {
120                 throw failed_constructor();
121         }
122
123         if ((_handle = _descriptor->instantiate (_descriptor, rate)) == 0) {
124                 throw failed_constructor();
125         }
126
127         port_cnt = parameter_count();
128
129         _control_data = new LADSPA_Data[port_cnt];
130         memset (_control_data, 0, sizeof (LADSPA_Data) * port_cnt);
131         _shadow_data = new LADSPA_Data[port_cnt];
132         memset (_shadow_data, 0, sizeof (LADSPA_Data) * port_cnt);
133
134         for (i = 0; i < port_cnt; ++i) {
135                 if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
136                         connect_port (i, &_control_data[i]);
137
138                         if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) &&
139                             strcmp (port_names()[i], X_("latency")) == 0) {
140                                 _latency_control_port = &_control_data[i];
141                                 *_latency_control_port = 0;
142                         }
143
144                         _shadow_data[i] = _default_value (i);
145                         _control_data[i] = _shadow_data[i];
146                 }
147         }
148
149         latency_compute_run ();
150 }
151
152 LadspaPlugin::~LadspaPlugin ()
153 {
154         deactivate ();
155         cleanup ();
156
157         // glib has internal reference counting on modules so this is ok
158         delete _module;
159
160         delete [] _control_data;
161         delete [] _shadow_data;
162 }
163
164 string
165 LadspaPlugin::unique_id() const
166 {
167         char buf[32];
168         snprintf (buf, sizeof (buf), "%lu", _descriptor->UniqueID);
169         return string (buf);
170 }
171
172 float
173 LadspaPlugin::_default_value (uint32_t port) const
174 {
175         const LADSPA_PortRangeHint *prh = port_range_hints();
176         float ret = 0.0f;
177         bool bounds_given = false;
178         bool sr_scaling = false;
179         bool earlier_hint = false;
180
181         /* defaults - case 1 */
182
183         if (LADSPA_IS_HINT_HAS_DEFAULT(prh[port].HintDescriptor)) {
184                 if (LADSPA_IS_HINT_DEFAULT_MINIMUM(prh[port].HintDescriptor)) {
185                         ret = prh[port].LowerBound;
186                         bounds_given = true;
187                         sr_scaling = true;
188                 }
189
190                 else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) {
191                         ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f;
192                         bounds_given = true;
193                         sr_scaling = true;
194                 }
195                 else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) {
196                         ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f;
197                         bounds_given = true;
198                         sr_scaling = true;
199                 }
200                 else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) {
201                         ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f;
202                         bounds_given = true;
203                         sr_scaling = true;
204                 }
205                 else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(prh[port].HintDescriptor)) {
206                         ret = prh[port].UpperBound;
207                         bounds_given = true;
208                         sr_scaling = true;
209                 }
210                 else if (LADSPA_IS_HINT_DEFAULT_0(prh[port].HintDescriptor)) {
211                         ret = 0.0f;
212                         earlier_hint = true;
213                 }
214                 else if (LADSPA_IS_HINT_DEFAULT_1(prh[port].HintDescriptor)) {
215                         ret = 1.0f;
216                         earlier_hint = true;
217                 }
218                 else if (LADSPA_IS_HINT_DEFAULT_100(prh[port].HintDescriptor)) {
219                         ret = 100.0f;
220                         earlier_hint = true;
221                 }
222                 else if (LADSPA_IS_HINT_DEFAULT_440(prh[port].HintDescriptor)) {
223                         ret = 440.0f;
224                         earlier_hint = true;
225                 }
226                 else {
227                         /* no hint found */
228                         ret = 0.0f;
229                 }
230         }
231
232         /* defaults - case 2 */
233         else if (LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) &&
234                  !LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) {
235
236                 if (prh[port].LowerBound < 0) {
237                         ret = 0.0f;
238                 } else {
239                         ret = prh[port].LowerBound;
240                 }
241
242                 bounds_given = true;
243                 sr_scaling = true;
244         }
245
246         /* defaults - case 3 */
247         else if (!LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) &&
248                  LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) {
249
250                 if (prh[port].UpperBound > 0) {
251                         ret = 0.0f;
252                 } else {
253                         ret = prh[port].UpperBound;
254                 }
255
256                 bounds_given = true;
257                 sr_scaling = true;
258         }
259
260         /* defaults - case 4 */
261         else if (LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) &&
262                  LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) {
263
264                 if (prh[port].LowerBound < 0 && prh[port].UpperBound > 0) {
265                         ret = 0.0f;
266                 } else if (prh[port].LowerBound < 0 && prh[port].UpperBound < 0) {
267                         ret = prh[port].UpperBound;
268                 } else {
269                         ret = prh[port].LowerBound;
270                 }
271                 bounds_given = true;
272                 sr_scaling = true;
273         }
274
275         /* defaults - case 5 */
276
277         if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) {
278                 if (bounds_given) {
279                         if (sr_scaling) {
280                                 ret *= _sample_rate;
281                         }
282                 } else {
283                         ret = _sample_rate;
284                 }
285         }
286
287         return ret;
288 }
289
290 void
291 LadspaPlugin::set_parameter (uint32_t which, float val)
292 {
293         if (which < _descriptor->PortCount) {
294
295                 if (get_parameter (which) == val) {
296                         return;
297                 }
298
299                 _shadow_data[which] = (LADSPA_Data) val;
300
301 #if 0
302                 if (which < parameter_count() && controls[which]) {
303                         controls[which]->Changed ();
304                 }
305 #endif
306
307         } else {
308                 warning << string_compose (_("illegal parameter number used with plugin \"%1\". This may "
309                                              "indicate a change in the plugin design, and presets may be "
310                                              "invalid"), name())
311                         << endmsg;
312         }
313
314         Plugin::set_parameter (which, val);
315 }
316
317 /** @return `plugin' value */
318 float
319 LadspaPlugin::get_parameter (uint32_t which) const
320 {
321         if (LADSPA_IS_PORT_INPUT(port_descriptor (which))) {
322                 return (float) _shadow_data[which];
323         } else {
324                 return (float) _control_data[which];
325         }
326 }
327
328 uint32_t
329 LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const
330 {
331         uint32_t x, c;
332
333         ok = false;
334
335         for (c = 0, x = 0; x < _descriptor->PortCount; ++x) {
336                 if (LADSPA_IS_PORT_CONTROL (port_descriptor (x))) {
337                         if (c++ == n) {
338                                 ok = true;
339                                 return x;
340                         }
341                 }
342         }
343         return 0;
344 }
345
346 void
347 LadspaPlugin::add_state (XMLNode* root) const
348 {
349         XMLNode *child;
350         char buf[32];
351         LocaleGuard lg;
352
353         for (uint32_t i = 0; i < parameter_count(); ++i){
354
355                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
356                     LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
357
358                         child = new XMLNode("Port");
359                         snprintf(buf, sizeof(buf), "%u", i);
360                         child->add_property("number", string(buf));
361                         snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
362                         child->add_property("value", string(buf));
363                         root->add_child_nocopy (*child);
364                 }
365         }
366 }
367
368 int
369 LadspaPlugin::set_state (const XMLNode& node, int version)
370 {
371         if (version < 3000) {
372                 return set_state_2X (node, version);
373         }
374
375 #ifndef NO_PLUGIN_STATE
376         XMLNodeList nodes;
377         XMLProperty const * prop;
378         XMLNodeConstIterator iter;
379         XMLNode *child;
380         const char *port;
381         const char *data;
382         uint32_t port_id;
383 #endif
384         LocaleGuard lg;
385
386         if (node.name() != state_node_name()) {
387                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
388                 return -1;
389         }
390
391 #ifndef NO_PLUGIN_STATE
392
393         nodes = node.children ("Port");
394
395         for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
396
397                 child = *iter;
398
399                 if ((prop = child->property("number")) != 0) {
400                         port = prop->value().c_str();
401                 } else {
402                         warning << _("LADSPA: no ladspa port number") << endmsg;
403                         continue;
404                 }
405                 if ((prop = child->property("value")) != 0) {
406                         data = prop->value().c_str();
407                 } else {
408                         warning << _("LADSPA: no ladspa port data") << endmsg;
409                         continue;
410                 }
411
412                 sscanf (port, "%" PRIu32, &port_id);
413                 set_parameter (port_id, atof(data));
414         }
415 #endif
416
417         latency_compute_run ();
418
419         return Plugin::set_state (node, version);
420 }
421
422 int
423 LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */)
424 {
425 #ifndef NO_PLUGIN_STATE
426         XMLNodeList nodes;
427         XMLProperty const * prop;
428         XMLNodeConstIterator iter;
429         XMLNode *child;
430         const char *port;
431         const char *data;
432         uint32_t port_id;
433 #endif
434         LocaleGuard lg;
435
436         if (node.name() != state_node_name()) {
437                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
438                 return -1;
439         }
440
441 #ifndef NO_PLUGIN_STATE
442         nodes = node.children ("port");
443
444         for(iter = nodes.begin(); iter != nodes.end(); ++iter){
445
446                 child = *iter;
447
448                 if ((prop = child->property("number")) != 0) {
449                         port = prop->value().c_str();
450                 } else {
451                         warning << _("LADSPA: no ladspa port number") << endmsg;
452                         continue;
453                 }
454                 if ((prop = child->property("value")) != 0) {
455                         data = prop->value().c_str();
456                 } else {
457                         warning << _("LADSPA: no ladspa port data") << endmsg;
458                         continue;
459                 }
460
461                 sscanf (port, "%" PRIu32, &port_id);
462                 set_parameter (port_id, atof(data));
463         }
464
465         latency_compute_run ();
466 #endif
467
468         return 0;
469 }
470
471 int
472 LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
473 {
474         LADSPA_PortRangeHint prh;
475
476         prh  = port_range_hints()[which];
477
478
479         if (LADSPA_IS_HINT_BOUNDED_BELOW(prh.HintDescriptor)) {
480                 desc.min_unbound = false;
481                 if (LADSPA_IS_HINT_SAMPLE_RATE(prh.HintDescriptor)) {
482                         desc.lower = prh.LowerBound * _session.frame_rate();
483                 } else {
484                         desc.lower = prh.LowerBound;
485                 }
486         } else {
487                 desc.min_unbound = true;
488                 desc.lower = 0;
489         }
490
491
492         if (LADSPA_IS_HINT_BOUNDED_ABOVE(prh.HintDescriptor)) {
493                 desc.max_unbound = false;
494                 if (LADSPA_IS_HINT_SAMPLE_RATE(prh.HintDescriptor)) {
495                         desc.upper = prh.UpperBound * _session.frame_rate();
496                 } else {
497                         desc.upper = prh.UpperBound;
498                 }
499         } else {
500                 desc.max_unbound = true;
501                 desc.upper = 4; /* completely arbitrary */
502         }
503
504         if (LADSPA_IS_HINT_HAS_DEFAULT (prh.HintDescriptor)) {
505                 desc.normal = _default_value(which);
506         } else {
507                 /* if there is no explicit hint for the default
508                  * value, use lower bound. This is not great but
509                  * better than just assuming '0' which may be out-of range.
510                  */
511                 desc.normal = desc.lower;
512         }
513
514         desc.toggled = LADSPA_IS_HINT_TOGGLED (prh.HintDescriptor);
515         desc.logarithmic = LADSPA_IS_HINT_LOGARITHMIC (prh.HintDescriptor);
516         desc.sr_dependent = LADSPA_IS_HINT_SAMPLE_RATE (prh.HintDescriptor);
517         desc.integer_step = LADSPA_IS_HINT_INTEGER (prh.HintDescriptor);
518
519         desc.label = port_names()[which];
520
521         desc.scale_points = get_scale_points(which);
522         desc.update_steps();
523
524         return 0;
525 }
526
527 string
528 LadspaPlugin::describe_parameter (Evoral::Parameter which)
529 {
530         if (which.type() == PluginAutomation && which.id() < parameter_count()) {
531                 return port_names()[which.id()];
532         } else {
533                 return "??";
534         }
535 }
536
537 ARDOUR::framecnt_t
538 LadspaPlugin::signal_latency () const
539 {
540         if (_user_latency) {
541                 return _user_latency;
542         }
543
544         if (_latency_control_port) {
545                 return (framecnt_t) floor (*_latency_control_port);
546         } else {
547                 return 0;
548         }
549 }
550
551 set<Evoral::Parameter>
552 LadspaPlugin::automatable () const
553 {
554         set<Evoral::Parameter> ret;
555
556         for (uint32_t i = 0; i < parameter_count(); ++i){
557                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
558                     LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
559
560                         ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
561                 }
562         }
563
564         return ret;
565 }
566
567 int
568 LadspaPlugin::connect_and_run (BufferSet& bufs,
569                 framepos_t start, framepos_t end, double speed,
570                 ChanMapping in_map, ChanMapping out_map,
571                 pframes_t nframes, framecnt_t offset)
572 {
573         Plugin::connect_and_run (bufs, start, end, speed, in_map, out_map, nframes, offset);
574
575         cycles_t now;
576         cycles_t then = get_cycles ();
577
578         BufferSet& silent_bufs  = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
579         BufferSet& scratch_bufs = _session.get_scratch_buffers(ChanCount(DataType::AUDIO, 1));
580
581         uint32_t audio_in_index  = 0;
582         uint32_t audio_out_index = 0;
583         bool valid;
584         for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
585                 if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) {
586                         if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) {
587                                 const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
588                                 connect_port(port_index,
589                                              valid ? bufs.get_audio(buf_index).data(offset)
590                                                    : silent_bufs.get_audio(0).data(offset));
591                         } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) {
592                                 const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
593                                 connect_port(port_index,
594                                              valid ? bufs.get_audio(buf_index).data(offset)
595                                                    : scratch_bufs.get_audio(0).data(offset));
596                         }
597                 }
598         }
599
600         run_in_place (nframes);
601         now = get_cycles ();
602         set_cycles ((uint32_t) (now - then));
603
604         return 0;
605 }
606
607 bool
608 LadspaPlugin::parameter_is_control (uint32_t param) const
609 {
610         return LADSPA_IS_PORT_CONTROL(port_descriptor (param));
611 }
612
613 bool
614 LadspaPlugin::parameter_is_audio (uint32_t param) const
615 {
616         return LADSPA_IS_PORT_AUDIO(port_descriptor (param));
617 }
618
619 bool
620 LadspaPlugin::parameter_is_output (uint32_t param) const
621 {
622         return LADSPA_IS_PORT_OUTPUT(port_descriptor (param));
623 }
624
625 bool
626 LadspaPlugin::parameter_is_input (uint32_t param) const
627 {
628         return LADSPA_IS_PORT_INPUT(port_descriptor (param));
629 }
630
631 void
632 LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
633 {
634         if (buf && len) {
635                 if (param < parameter_count()) {
636                         snprintf (buf, len, "%.3f", get_parameter (param));
637                 } else {
638                         strcat (buf, "0");
639                 }
640         }
641 }
642
643 boost::shared_ptr<ScalePoints>
644 LadspaPlugin::get_scale_points(uint32_t port_index) const
645 {
646         boost::shared_ptr<ScalePoints> ret;
647 #ifdef HAVE_LRDF
648         const uint32_t id     = atol(unique_id().c_str());
649         lrdf_defaults* points = lrdf_get_scale_values(id, port_index);
650
651         if (!points) {
652                 return ret;
653         }
654
655         ret = boost::shared_ptr<ScalePoints>(new ScalePoints());
656
657         for (uint32_t i = 0; i < points->count; ++i) {
658                 ret->insert(make_pair(points->items[i].label,
659                                       points->items[i].value));
660         }
661
662         lrdf_free_setting_values(points);
663 #endif
664         return ret;
665 }
666
667 void
668 LadspaPlugin::run_in_place (pframes_t nframes)
669 {
670         for (uint32_t i = 0; i < parameter_count(); ++i) {
671                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
672                         _control_data[i] = _shadow_data[i];
673                 }
674         }
675
676         assert (_was_activated);
677
678         _descriptor->run (_handle, nframes);
679 }
680
681 void
682 LadspaPlugin::latency_compute_run ()
683 {
684         if (!_latency_control_port) {
685                 return;
686         }
687
688         /* we need to run the plugin so that it can set its latency
689            parameter.
690         */
691
692         activate ();
693
694         uint32_t port_index = 0;
695         uint32_t in_index = 0;
696         uint32_t out_index = 0;
697         const framecnt_t bufsize = 1024;
698         LADSPA_Data buffer[bufsize];
699
700         memset(buffer,0,sizeof(LADSPA_Data)*bufsize);
701
702         /* Note that we've already required that plugins
703            be able to handle in-place processing.
704         */
705
706         port_index = 0;
707
708         while (port_index < parameter_count()) {
709                 if (LADSPA_IS_PORT_AUDIO (port_descriptor (port_index))) {
710                         if (LADSPA_IS_PORT_INPUT (port_descriptor (port_index))) {
711                                 connect_port (port_index, buffer);
712                                 in_index++;
713                         } else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) {
714                                 connect_port (port_index, buffer);
715                                 out_index++;
716                         }
717                 }
718                 port_index++;
719         }
720
721         run_in_place (bufsize);
722         deactivate ();
723 }
724
725 PluginPtr
726 LadspaPluginInfo::load (Session& session)
727 {
728         try {
729                 PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate()));
730                 plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
731                 return plugin;
732         }
733
734         catch (failed_constructor &err) {
735                 return PluginPtr ((Plugin*) 0);
736         }
737 }
738
739 std::vector<Plugin::PresetRecord>
740 LadspaPluginInfo::get_presets (bool /*user_only*/) const
741 {
742         std::vector<Plugin::PresetRecord> p;
743 #if (defined HAVE_LRDF && !defined NO_PLUGIN_STATE)
744         if (!isdigit (unique_id[0])) {
745                 return p;
746         }
747         uint32_t id = atol (unique_id);
748         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
749
750         if (set_uris) {
751                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
752                         if (char* label = lrdf_get_label (set_uris->items[i])) {
753                                 p.push_back (Plugin::PresetRecord (set_uris->items[i], label));
754                         }
755                 }
756                 lrdf_free_uris(set_uris);
757         }
758 #endif
759         return p;
760 }
761
762 LadspaPluginInfo::LadspaPluginInfo()
763 {
764        type = ARDOUR::LADSPA;
765 }
766
767
768 void
769 LadspaPlugin::find_presets ()
770 {
771 #ifdef HAVE_LRDF
772         uint32_t id;
773         std::string unique (unique_id());
774
775         if (!isdigit (unique[0])) {
776                 return;
777         }
778
779         id = atol (unique.c_str());
780
781         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
782
783         if (set_uris) {
784                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
785                         if (char* label = lrdf_get_label(set_uris->items[i])) {
786                                 PresetRecord rec (set_uris->items[i], label);
787                                 _presets.insert (make_pair (set_uris->items[i], rec));
788                         }
789                 }
790                 lrdf_free_uris(set_uris);
791         }
792 #endif
793 }
794
795
796 bool
797 LadspaPlugin::load_preset (PresetRecord r)
798 {
799 #ifdef HAVE_LRDF
800         lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str());
801
802         if (defs) {
803                 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
804                         if (parameter_is_input (defs->items[i].pid)) {
805                                 set_parameter(defs->items[i].pid, defs->items[i].value);
806                         }
807                 }
808                 lrdf_free_setting_values(defs);
809         }
810
811         Plugin::load_preset (r);
812 #endif
813         return true;
814 }
815
816 #ifdef HAVE_LRDF
817 /* XXX: should be in liblrdf */
818 static void
819 lrdf_remove_preset (const char* /*source*/, const char *setting_uri)
820 {
821         lrdf_statement p;
822         lrdf_statement *q;
823         lrdf_statement *i;
824         char setting_uri_copy[64];
825         char buf[64];
826
827         strncpy(setting_uri_copy, setting_uri, sizeof(setting_uri_copy));
828
829         p.subject = setting_uri_copy;
830         strncpy(buf, LADSPA_BASE "hasPortValue", sizeof(buf));
831         p.predicate = buf;
832         p.object = NULL;
833         q = lrdf_matches(&p);
834
835         p.predicate = NULL;
836         p.object = NULL;
837         for (i = q; i; i = i->next) {
838                 p.subject = i->object;
839                 lrdf_remove_matches(&p);
840         }
841
842         lrdf_free_statements(q);
843
844         p.subject = NULL;
845         strncpy(buf, LADSPA_BASE "hasSetting", sizeof(buf));
846         p.predicate = buf;
847         p.object = setting_uri_copy;
848         lrdf_remove_matches(&p);
849
850         p.subject = setting_uri_copy;
851         p.predicate = NULL;
852         p.object = NULL;
853         lrdf_remove_matches (&p);
854 }
855 #endif
856
857 void
858 LadspaPlugin::do_remove_preset (string name)
859 {
860 #ifdef HAVE_LRDF
861         string const envvar = preset_envvar ();
862         if (envvar.empty()) {
863                 warning << _("Could not locate HOME.  Preset not removed.") << endmsg;
864                 return;
865         }
866
867         Plugin::PresetRecord const * p = preset_by_label (name);
868         if (!p) {
869                 return;
870         }
871
872         string const source = preset_source (envvar);
873         lrdf_remove_preset (source.c_str(), p->uri.c_str ());
874
875         write_preset_file (envvar);
876 #endif
877 }
878
879 string
880 LadspaPlugin::preset_envvar () const
881 {
882         char* envvar;
883         if ((envvar = getenv ("HOME")) == 0) {
884                 return "";
885         }
886
887         return envvar;
888 }
889
890 string
891 LadspaPlugin::preset_source (string envvar) const
892 {
893         return string_compose ("file:%1/.ladspa/rdf/ardour-presets.n3", envvar);
894 }
895
896 bool
897 LadspaPlugin::write_preset_file (string envvar)
898 {
899 #ifdef HAVE_LRDF
900         string path = string_compose("%1/.ladspa", envvar);
901         if (g_mkdir_with_parents (path.c_str(), 0775)) {
902                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
903                 return false;
904         }
905
906         path += "/rdf";
907         if (g_mkdir_with_parents (path.c_str(), 0775)) {
908                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
909                 return false;
910         }
911
912         string const source = preset_source (envvar);
913
914         if (lrdf_export_by_source (source.c_str(), source.substr(5).c_str())) {
915                 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
916                 return false;
917         }
918
919         return true;
920 #else
921         return false;
922 #endif
923 }
924
925 string
926 LadspaPlugin::do_save_preset (string name)
927 {
928 #ifdef HAVE_LRDF
929         /* make a vector of pids that are input parameters */
930         vector<int> input_parameter_pids;
931         for (uint32_t i = 0; i < parameter_count(); ++i) {
932                 if (parameter_is_input (i)) {
933                         input_parameter_pids.push_back (i);
934                 }
935         }
936
937         std::string unique (unique_id());
938
939         if (!isdigit (unique[0])) {
940                 return "";
941         }
942
943         uint32_t const id = atol (unique.c_str());
944
945         lrdf_defaults defaults;
946         defaults.count = input_parameter_pids.size ();
947         std::vector<lrdf_portvalue> portvalues(input_parameter_pids.size());
948         defaults.items = &portvalues[0];
949
950         for (vector<int>::size_type i = 0; i < input_parameter_pids.size(); ++i) {
951                 portvalues[i].pid = input_parameter_pids[i];
952                 portvalues[i].value = get_parameter (input_parameter_pids[i]);
953         }
954
955         string const envvar = preset_envvar ();
956         if (envvar.empty()) {
957                 warning << _("Could not locate HOME.  Preset not saved.") << endmsg;
958                 return "";
959         }
960
961         string const source = preset_source (envvar);
962
963         char* uri_char = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults);
964         string uri (uri_char);
965         free (uri_char);
966
967         if (!write_preset_file (envvar)) {
968                 return "";
969         }
970
971         return uri;
972 #else
973         return string();
974 #endif
975 }
976
977 LADSPA_PortDescriptor
978 LadspaPlugin::port_descriptor (uint32_t i) const
979 {
980         if (i < _descriptor->PortCount) {
981                 return _descriptor->PortDescriptors[i];
982         }
983
984         warning << "LADSPA plugin port index " << i << " out of range." << endmsg;
985         return 0;
986 }
987
988
989