6ee810f6b1bd4ef176e388d6101fbb2ba991fc37
[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 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <cerrno>
35
36 #ifdef HAVE_LRDF
37 #include <lrdf.h>
38 #endif
39
40 #include "pbd/compose.h"
41 #include "pbd/error.h"
42 #include "pbd/xml++.h"
43
44 #include "midi++/manager.h"
45
46 #include "ardour/session.h"
47 #include "ardour/ladspa_plugin.h"
48 #include "ardour/buffer_set.h"
49 #include "ardour/audio_buffer.h"
50
51 #include "pbd/stl_delete.h"
52
53 #include "i18n.h"
54 #include <locale.h>
55
56 using namespace std;
57 using namespace ARDOUR;
58 using namespace PBD;
59
60 LadspaPlugin::LadspaPlugin (string module_path, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate)
61         : Plugin (e, session)
62 {
63         init (module_path, index, rate);
64 }
65
66 LadspaPlugin::LadspaPlugin (const LadspaPlugin &other)
67         : Plugin (other)
68 {
69         init (other._module_path, other._index, other._sample_rate);
70
71         for (uint32_t i = 0; i < parameter_count(); ++i) {
72                 _control_data[i] = other._shadow_data[i];
73                 _shadow_data[i] = other._shadow_data[i];
74         }
75 }
76
77 void
78 LadspaPlugin::init (string module_path, uint32_t index, framecnt_t rate)
79 {
80         void* func;
81         LADSPA_Descriptor_Function dfunc;
82         uint32_t i, port_cnt;
83
84         _module_path = module_path;
85         _module = new Glib::Module(_module_path);
86         _control_data = 0;
87         _shadow_data = 0;
88         _latency_control_port = 0;
89         _was_activated = false;
90
91         if (!(*_module)) {
92                 error << _("LADSPA: Unable to open module: ") << Glib::Module::get_last_error() << endmsg;
93                 delete _module;
94                 throw failed_constructor();
95         }
96
97         if (!_module->get_symbol("ladspa_descriptor", func)) {
98                 error << _("LADSPA: module has no descriptor function.") << endmsg;
99                 throw failed_constructor();
100         }
101
102         dfunc = (LADSPA_Descriptor_Function)func;
103
104         if ((_descriptor = dfunc (index)) == 0) {
105                 error << _("LADSPA: plugin has gone away since discovery!") << endmsg;
106                 throw failed_constructor();
107         }
108
109         _index = index;
110
111         if (LADSPA_IS_INPLACE_BROKEN(_descriptor->Properties)) {
112                 error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), _descriptor->Name) << endmsg;
113                 throw failed_constructor();
114         }
115
116         _sample_rate = rate;
117
118         if (_descriptor->instantiate == 0) {
119                 throw failed_constructor();
120         }
121
122         if ((_handle = _descriptor->instantiate (_descriptor, rate)) == 0) {
123                 throw failed_constructor();
124         }
125
126         port_cnt = parameter_count();
127
128         _control_data = new LADSPA_Data[port_cnt];
129         _shadow_data = new LADSPA_Data[port_cnt];
130
131         for (i = 0; i < port_cnt; ++i) {
132                 if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
133                         connect_port (i, &_control_data[i]);
134
135                         if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) &&
136                             strcmp (port_names()[i], X_("latency")) == 0) {
137                                 _latency_control_port = &_control_data[i];
138                                 *_latency_control_port = 0;
139                         }
140
141                         if (!LADSPA_IS_PORT_INPUT(port_descriptor (i))) {
142                                 continue;
143                         }
144
145                         _shadow_data[i] = default_value (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)
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[16];
351         LocaleGuard lg (X_("POSIX"));
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         XMLNodeList nodes;
376         XMLProperty *prop;
377         XMLNodeConstIterator iter;
378         XMLNode *child;
379         const char *port;
380         const char *data;
381         uint32_t port_id;
382         LocaleGuard lg (X_("POSIX"));
383
384         if (node.name() != state_node_name()) {
385                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
386                 return -1;
387         }
388
389         nodes = node.children ("Port");
390
391         for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
392
393                 child = *iter;
394
395                 if ((prop = child->property("number")) != 0) {
396                         port = prop->value().c_str();
397                 } else {
398                         warning << _("LADSPA: no ladspa port number") << endmsg;
399                         continue;
400                 }
401                 if ((prop = child->property("value")) != 0) {
402                         data = prop->value().c_str();
403                 } else {
404                         warning << _("LADSPA: no ladspa port data") << endmsg;
405                         continue;
406                 }
407
408                 sscanf (port, "%" PRIu32, &port_id);
409                 set_parameter (port_id, atof(data));
410         }
411
412         latency_compute_run ();
413
414         return Plugin::set_state (node, version);
415 }
416
417 int
418 LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */)
419 {
420         XMLNodeList nodes;
421         XMLProperty *prop;
422         XMLNodeConstIterator iter;
423         XMLNode *child;
424         const char *port;
425         const char *data;
426         uint32_t port_id;
427         LocaleGuard lg (X_("POSIX"));
428
429         if (node.name() != state_node_name()) {
430                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
431                 return -1;
432         }
433
434         nodes = node.children ("port");
435
436         for(iter = nodes.begin(); iter != nodes.end(); ++iter){
437
438                 child = *iter;
439
440                 if ((prop = child->property("number")) != 0) {
441                         port = prop->value().c_str();
442                 } else {
443                         warning << _("LADSPA: no ladspa port number") << endmsg;
444                         continue;
445                 }
446                 if ((prop = child->property("value")) != 0) {
447                         data = prop->value().c_str();
448                 } else {
449                         warning << _("LADSPA: no ladspa port data") << endmsg;
450                         continue;
451                 }
452
453                 sscanf (port, "%" PRIu32, &port_id);
454                 set_parameter (port_id, atof(data));
455         }
456
457         latency_compute_run ();
458
459         return 0;
460 }
461
462 int
463 LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
464 {
465         LADSPA_PortRangeHint prh;
466
467         prh  = port_range_hints()[which];
468
469
470         if (LADSPA_IS_HINT_BOUNDED_BELOW(prh.HintDescriptor)) {
471                 desc.min_unbound = false;
472                 if (LADSPA_IS_HINT_SAMPLE_RATE(prh.HintDescriptor)) {
473                         desc.lower = prh.LowerBound * _session.frame_rate();
474                 } else {
475                         desc.lower = prh.LowerBound;
476                 }
477         } else {
478                 desc.min_unbound = true;
479                 desc.lower = 0;
480         }
481
482
483         if (LADSPA_IS_HINT_BOUNDED_ABOVE(prh.HintDescriptor)) {
484                 desc.max_unbound = false;
485                 if (LADSPA_IS_HINT_SAMPLE_RATE(prh.HintDescriptor)) {
486                         desc.upper = prh.UpperBound * _session.frame_rate();
487                 } else {
488                         desc.upper = prh.UpperBound;
489                 }
490         } else {
491                 desc.max_unbound = true;
492                 desc.upper = 4; /* completely arbitrary */
493         }
494
495         if (LADSPA_IS_HINT_INTEGER (prh.HintDescriptor)) {
496                 desc.step = 1.0;
497                 desc.smallstep = 0.1;
498                 desc.largestep = 10.0;
499         } else {
500                 float delta = desc.upper - desc.lower;
501                 desc.step = delta / 1000.0f;
502                 desc.smallstep = delta / 10000.0f;
503                 desc.largestep = delta/10.0f;
504         }
505
506         desc.toggled = LADSPA_IS_HINT_TOGGLED (prh.HintDescriptor);
507         desc.logarithmic = LADSPA_IS_HINT_LOGARITHMIC (prh.HintDescriptor);
508         desc.sr_dependent = LADSPA_IS_HINT_SAMPLE_RATE (prh.HintDescriptor);
509         desc.integer_step = LADSPA_IS_HINT_INTEGER (prh.HintDescriptor);
510
511         desc.label = port_names()[which];
512
513         return 0;
514 }
515
516 string
517 LadspaPlugin::describe_parameter (Evoral::Parameter which)
518 {
519         if (which.type() == PluginAutomation && which.id() < parameter_count()) {
520                 return port_names()[which.id()];
521         } else {
522                 return "??";
523         }
524 }
525
526 ARDOUR::framecnt_t
527 LadspaPlugin::signal_latency () const
528 {
529         if (_user_latency) {
530                 return _user_latency;
531         }
532
533         if (_latency_control_port) {
534                 return (framecnt_t) floor (*_latency_control_port);
535         } else {
536                 return 0;
537         }
538 }
539
540 set<Evoral::Parameter>
541 LadspaPlugin::automatable () const
542 {
543         set<Evoral::Parameter> ret;
544
545         for (uint32_t i = 0; i < parameter_count(); ++i){
546                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
547                     LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
548
549                         ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
550                 }
551         }
552
553         return ret;
554 }
555
556 int
557 LadspaPlugin::connect_and_run (BufferSet& bufs,
558                 ChanMapping in_map, ChanMapping out_map,
559                 pframes_t nframes, framecnt_t offset)
560 {
561         Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
562
563         cycles_t now;
564         cycles_t then = get_cycles ();
565
566         BufferSet& silent_bufs  = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
567         BufferSet& scratch_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
568
569         uint32_t audio_in_index  = 0;
570         uint32_t audio_out_index = 0;
571         bool valid;
572         for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
573                 if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) {
574                         if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) {
575                                 const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
576                                 connect_port(port_index,
577                                              valid ? bufs.get_audio(buf_index).data(offset)
578                                                    : silent_bufs.get_audio(0).data(offset));
579                         } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) {
580                                 const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
581                                 connect_port(port_index,
582                                              valid ? bufs.get_audio(buf_index).data(offset)
583                                                    : scratch_bufs.get_audio(0).data(offset));
584                         }
585                 }
586         }
587
588         run_in_place (nframes);
589         now = get_cycles ();
590         set_cycles ((uint32_t) (now - then));
591
592         return 0;
593 }
594
595 bool
596 LadspaPlugin::parameter_is_control (uint32_t param) const
597 {
598         return LADSPA_IS_PORT_CONTROL(port_descriptor (param));
599 }
600
601 bool
602 LadspaPlugin::parameter_is_audio (uint32_t param) const
603 {
604         return LADSPA_IS_PORT_AUDIO(port_descriptor (param));
605 }
606
607 bool
608 LadspaPlugin::parameter_is_output (uint32_t param) const
609 {
610         return LADSPA_IS_PORT_OUTPUT(port_descriptor (param));
611 }
612
613 bool
614 LadspaPlugin::parameter_is_input (uint32_t param) const
615 {
616         return LADSPA_IS_PORT_INPUT(port_descriptor (param));
617 }
618
619 void
620 LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
621 {
622         if (buf && len) {
623                 if (param < parameter_count()) {
624                         snprintf (buf, len, "%.3f", get_parameter (param));
625                 } else {
626                         strcat (buf, "0");
627                 }
628         }
629 }
630
631 boost::shared_ptr<Plugin::ScalePoints>
632 LadspaPlugin::get_scale_points(uint32_t port_index) const
633 {
634         boost::shared_ptr<Plugin::ScalePoints> ret;
635 #ifdef HAVE_LRDF
636         const uint32_t id     = atol(unique_id().c_str());
637         lrdf_defaults* points = lrdf_get_scale_values(id, port_index);
638
639         if (!points) {
640                 return ret;
641         }
642
643         ret = boost::shared_ptr<Plugin::ScalePoints>(new ScalePoints());
644
645         for (uint32_t i = 0; i < points->count; ++i) {
646                 ret->insert(make_pair(points->items[i].label,
647                                       points->items[i].value));
648         }
649
650         lrdf_free_setting_values(points);
651 #endif
652         return ret;
653 }
654
655 void
656 LadspaPlugin::run_in_place (pframes_t nframes)
657 {
658         for (uint32_t i = 0; i < parameter_count(); ++i) {
659                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
660                         _control_data[i] = _shadow_data[i];
661                 }
662         }
663
664         assert (_was_activated);
665
666         _descriptor->run (_handle, nframes);
667 }
668
669 void
670 LadspaPlugin::latency_compute_run ()
671 {
672         if (!_latency_control_port) {
673                 return;
674         }
675
676         /* we need to run the plugin so that it can set its latency
677            parameter.
678         */
679
680         activate ();
681
682         uint32_t port_index = 0;
683         uint32_t in_index = 0;
684         uint32_t out_index = 0;
685         const framecnt_t bufsize = 1024;
686         LADSPA_Data buffer[bufsize];
687
688         memset(buffer,0,sizeof(LADSPA_Data)*bufsize);
689
690         /* Note that we've already required that plugins
691            be able to handle in-place processing.
692         */
693
694         port_index = 0;
695
696         while (port_index < parameter_count()) {
697                 if (LADSPA_IS_PORT_AUDIO (port_descriptor (port_index))) {
698                         if (LADSPA_IS_PORT_INPUT (port_descriptor (port_index))) {
699                                 connect_port (port_index, buffer);
700                                 in_index++;
701                         } else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) {
702                                 connect_port (port_index, buffer);
703                                 out_index++;
704                         }
705                 }
706                 port_index++;
707         }
708
709         run_in_place (bufsize);
710         deactivate ();
711 }
712
713 PluginPtr
714 LadspaPluginInfo::load (Session& session)
715 {
716         try {
717                 PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate()));
718                 plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
719                 return plugin;
720         }
721
722         catch (failed_constructor &err) {
723                 return PluginPtr ((Plugin*) 0);
724         }
725 }
726
727 LadspaPluginInfo::LadspaPluginInfo()
728 {
729        type = ARDOUR::LADSPA;
730 }
731
732
733 void
734 LadspaPlugin::find_presets ()
735 {
736 #ifdef HAVE_LRDF
737         uint32_t id;
738         std::string unique (unique_id());
739
740         if (!isdigit (unique[0])) {
741                 return;
742         }
743
744         id = atol (unique.c_str());
745
746         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
747
748         if (set_uris) {
749                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
750                         if (char* label = lrdf_get_label(set_uris->items[i])) {
751                                 PresetRecord rec (set_uris->items[i], label);
752                                 _presets.insert (make_pair (set_uris->items[i], rec));
753                         }
754                 }
755                 lrdf_free_uris(set_uris);
756         }
757 #endif
758 }
759
760
761 bool
762 LadspaPlugin::load_preset (PresetRecord r)
763 {
764 #ifdef HAVE_LRDF
765         lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str());
766
767         if (defs) {
768                 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
769                         if (parameter_is_input (defs->items[i].pid)) {
770                                 set_parameter(defs->items[i].pid, defs->items[i].value);
771                         }
772                 }
773                 lrdf_free_setting_values(defs);
774         }
775
776         Plugin::load_preset (r);
777 #endif
778         return true;
779 }
780
781 /* XXX: should be in liblrdf */
782 static void
783 lrdf_remove_preset (const char* /*source*/, const char *setting_uri)
784 {
785 #ifdef HAVE_LRDF
786         lrdf_statement p;
787         lrdf_statement *q;
788         lrdf_statement *i;
789         char setting_uri_copy[64];
790         char buf[64];
791
792         strncpy(setting_uri_copy, setting_uri, sizeof(setting_uri_copy));
793
794         p.subject = setting_uri_copy;
795         strncpy(buf, LADSPA_BASE "hasPortValue", sizeof(buf));
796         p.predicate = buf;
797         p.object = NULL;
798         q = lrdf_matches(&p);
799
800         p.predicate = NULL;
801         p.object = NULL;
802         for (i = q; i; i = i->next) {
803                 p.subject = i->object;
804                 lrdf_remove_matches(&p);
805         }
806
807         lrdf_free_statements(q);
808
809         p.subject = NULL;
810         strncpy(buf, LADSPA_BASE "hasSetting", sizeof(buf));
811         p.predicate = buf;
812         p.object = setting_uri_copy;
813         lrdf_remove_matches(&p);
814
815         p.subject = setting_uri_copy;
816         p.predicate = NULL;
817         p.object = NULL;
818         lrdf_remove_matches (&p);
819 #endif
820 }
821
822 void
823 LadspaPlugin::do_remove_preset (string name)
824 {
825 #ifdef HAVE_LRDF
826         string const envvar = preset_envvar ();
827         if (envvar.empty()) {
828                 warning << _("Could not locate HOME.  Preset not removed.") << endmsg;
829                 return;
830         }
831
832         Plugin::PresetRecord const * p = preset_by_label (name);
833         if (!p) {
834                 return;
835         }
836
837         string const source = preset_source (envvar);
838         lrdf_remove_preset (source.c_str(), p->uri.c_str ());
839
840         write_preset_file (envvar);
841 #endif
842 }
843
844 string
845 LadspaPlugin::preset_envvar () const
846 {
847         char* envvar;
848         if ((envvar = getenv ("HOME")) == 0) {
849                 return "";
850         }
851
852         return envvar;
853 }
854
855 string
856 LadspaPlugin::preset_source (string envvar) const
857 {
858         return string_compose ("file:%1/.ladspa/rdf/ardour-presets.n3", envvar);
859 }
860
861 bool
862 LadspaPlugin::write_preset_file (string envvar)
863 {
864 #ifdef HAVE_LRDF
865         string path = string_compose("%1/.ladspa", envvar);
866         if (g_mkdir_with_parents (path.c_str(), 0775)) {
867                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
868                 return false;
869         }
870
871         path += "/rdf";
872         if (g_mkdir_with_parents (path.c_str(), 0775)) {
873                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
874                 return false;
875         }
876
877         string const source = preset_source (envvar);
878
879         if (lrdf_export_by_source (source.c_str(), source.substr(5).c_str())) {
880                 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
881                 return false;
882         }
883
884         return true;
885 #else
886         return false;
887 #endif
888 }
889
890 string
891 LadspaPlugin::do_save_preset (string name)
892 {
893 #ifdef HAVE_LRDF
894         /* make a vector of pids that are input parameters */
895         vector<int> input_parameter_pids;
896         for (uint32_t i = 0; i < parameter_count(); ++i) {
897                 if (parameter_is_input (i)) {
898                         input_parameter_pids.push_back (i);
899                 }
900         }
901
902         std::string unique (unique_id());
903
904         if (!isdigit (unique[0])) {
905                 return "";
906         }
907
908         uint32_t const id = atol (unique.c_str());
909
910         lrdf_defaults defaults;
911         defaults.count = input_parameter_pids.size ();
912         lrdf_portvalue portvalues[input_parameter_pids.size()];
913         defaults.items = portvalues;
914
915         for (vector<int>::size_type i = 0; i < input_parameter_pids.size(); ++i) {
916                 portvalues[i].pid = input_parameter_pids[i];
917                 portvalues[i].value = get_parameter (input_parameter_pids[i]);
918         }
919
920         string const envvar = preset_envvar ();
921         if (envvar.empty()) {
922                 warning << _("Could not locate HOME.  Preset not saved.") << endmsg;
923                 return "";
924         }
925
926         string const source = preset_source (envvar);
927
928         char* uri_char = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults);
929         string uri (uri_char);
930         free (uri_char);
931
932         if (!write_preset_file (envvar)) {
933                 return "";
934         }
935
936         return uri;
937 #else
938         return string();
939 #endif
940 }
941
942 LADSPA_PortDescriptor
943 LadspaPlugin::port_descriptor (uint32_t i) const
944 {
945         if (i < _descriptor->PortCount) {               
946                 return _descriptor->PortDescriptors[i];
947         }
948         
949         warning << "LADSPA plugin port index " << i << " out of range." << endmsg;
950         return 0;
951 }
952
953                 
954