add Slavable API for VCA assign/unassign
[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 "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                 ChanMapping in_map, ChanMapping out_map,
570                 pframes_t nframes, framecnt_t offset)
571 {
572         Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
573
574         cycles_t now;
575         cycles_t then = get_cycles ();
576
577         BufferSet& silent_bufs  = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
578         BufferSet& scratch_bufs = _session.get_scratch_buffers(ChanCount(DataType::AUDIO, 1));
579
580         uint32_t audio_in_index  = 0;
581         uint32_t audio_out_index = 0;
582         bool valid;
583         for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
584                 if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) {
585                         if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) {
586                                 const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
587                                 connect_port(port_index,
588                                              valid ? bufs.get_audio(buf_index).data(offset)
589                                                    : silent_bufs.get_audio(0).data(offset));
590                         } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) {
591                                 const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
592                                 connect_port(port_index,
593                                              valid ? bufs.get_audio(buf_index).data(offset)
594                                                    : scratch_bufs.get_audio(0).data(offset));
595                         }
596                 }
597         }
598
599         run_in_place (nframes);
600         now = get_cycles ();
601         set_cycles ((uint32_t) (now - then));
602
603         return 0;
604 }
605
606 bool
607 LadspaPlugin::parameter_is_control (uint32_t param) const
608 {
609         return LADSPA_IS_PORT_CONTROL(port_descriptor (param));
610 }
611
612 bool
613 LadspaPlugin::parameter_is_audio (uint32_t param) const
614 {
615         return LADSPA_IS_PORT_AUDIO(port_descriptor (param));
616 }
617
618 bool
619 LadspaPlugin::parameter_is_output (uint32_t param) const
620 {
621         return LADSPA_IS_PORT_OUTPUT(port_descriptor (param));
622 }
623
624 bool
625 LadspaPlugin::parameter_is_input (uint32_t param) const
626 {
627         return LADSPA_IS_PORT_INPUT(port_descriptor (param));
628 }
629
630 void
631 LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
632 {
633         if (buf && len) {
634                 if (param < parameter_count()) {
635                         snprintf (buf, len, "%.3f", get_parameter (param));
636                 } else {
637                         strcat (buf, "0");
638                 }
639         }
640 }
641
642 boost::shared_ptr<ScalePoints>
643 LadspaPlugin::get_scale_points(uint32_t port_index) const
644 {
645         boost::shared_ptr<ScalePoints> ret;
646 #ifdef HAVE_LRDF
647         const uint32_t id     = atol(unique_id().c_str());
648         lrdf_defaults* points = lrdf_get_scale_values(id, port_index);
649
650         if (!points) {
651                 return ret;
652         }
653
654         ret = boost::shared_ptr<ScalePoints>(new ScalePoints());
655
656         for (uint32_t i = 0; i < points->count; ++i) {
657                 ret->insert(make_pair(points->items[i].label,
658                                       points->items[i].value));
659         }
660
661         lrdf_free_setting_values(points);
662 #endif
663         return ret;
664 }
665
666 void
667 LadspaPlugin::run_in_place (pframes_t nframes)
668 {
669         for (uint32_t i = 0; i < parameter_count(); ++i) {
670                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
671                         _control_data[i] = _shadow_data[i];
672                 }
673         }
674
675         assert (_was_activated);
676
677         _descriptor->run (_handle, nframes);
678 }
679
680 void
681 LadspaPlugin::latency_compute_run ()
682 {
683         if (!_latency_control_port) {
684                 return;
685         }
686
687         /* we need to run the plugin so that it can set its latency
688            parameter.
689         */
690
691         activate ();
692
693         uint32_t port_index = 0;
694         uint32_t in_index = 0;
695         uint32_t out_index = 0;
696         const framecnt_t bufsize = 1024;
697         LADSPA_Data buffer[bufsize];
698
699         memset(buffer,0,sizeof(LADSPA_Data)*bufsize);
700
701         /* Note that we've already required that plugins
702            be able to handle in-place processing.
703         */
704
705         port_index = 0;
706
707         while (port_index < parameter_count()) {
708                 if (LADSPA_IS_PORT_AUDIO (port_descriptor (port_index))) {
709                         if (LADSPA_IS_PORT_INPUT (port_descriptor (port_index))) {
710                                 connect_port (port_index, buffer);
711                                 in_index++;
712                         } else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) {
713                                 connect_port (port_index, buffer);
714                                 out_index++;
715                         }
716                 }
717                 port_index++;
718         }
719
720         run_in_place (bufsize);
721         deactivate ();
722 }
723
724 PluginPtr
725 LadspaPluginInfo::load (Session& session)
726 {
727         try {
728                 PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate()));
729                 plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
730                 return plugin;
731         }
732
733         catch (failed_constructor &err) {
734                 return PluginPtr ((Plugin*) 0);
735         }
736 }
737
738 std::vector<Plugin::PresetRecord>
739 LadspaPluginInfo::get_presets (bool /*user_only*/) const
740 {
741         std::vector<Plugin::PresetRecord> p;
742 #if (defined HAVE_LRDF && !defined NO_PLUGIN_STATE)
743         if (!isdigit (unique_id[0])) {
744                 return p;
745         }
746         uint32_t id = atol (unique_id);
747         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
748
749         if (set_uris) {
750                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
751                         if (char* label = lrdf_get_label (set_uris->items[i])) {
752                                 p.push_back (Plugin::PresetRecord (set_uris->items[i], label));
753                         }
754                 }
755                 lrdf_free_uris(set_uris);
756         }
757 #endif
758         return p;
759 }
760
761 LadspaPluginInfo::LadspaPluginInfo()
762 {
763        type = ARDOUR::LADSPA;
764 }
765
766
767 void
768 LadspaPlugin::find_presets ()
769 {
770 #ifdef HAVE_LRDF
771         uint32_t id;
772         std::string unique (unique_id());
773
774         if (!isdigit (unique[0])) {
775                 return;
776         }
777
778         id = atol (unique.c_str());
779
780         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
781
782         if (set_uris) {
783                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
784                         if (char* label = lrdf_get_label(set_uris->items[i])) {
785                                 PresetRecord rec (set_uris->items[i], label);
786                                 _presets.insert (make_pair (set_uris->items[i], rec));
787                         }
788                 }
789                 lrdf_free_uris(set_uris);
790         }
791 #endif
792 }
793
794
795 bool
796 LadspaPlugin::load_preset (PresetRecord r)
797 {
798 #ifdef HAVE_LRDF
799         lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str());
800
801         if (defs) {
802                 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
803                         if (parameter_is_input (defs->items[i].pid)) {
804                                 set_parameter(defs->items[i].pid, defs->items[i].value);
805                         }
806                 }
807                 lrdf_free_setting_values(defs);
808         }
809
810         Plugin::load_preset (r);
811 #endif
812         return true;
813 }
814
815 #ifdef HAVE_LRDF
816 /* XXX: should be in liblrdf */
817 static void
818 lrdf_remove_preset (const char* /*source*/, const char *setting_uri)
819 {
820         lrdf_statement p;
821         lrdf_statement *q;
822         lrdf_statement *i;
823         char setting_uri_copy[64];
824         char buf[64];
825
826         strncpy(setting_uri_copy, setting_uri, sizeof(setting_uri_copy));
827
828         p.subject = setting_uri_copy;
829         strncpy(buf, LADSPA_BASE "hasPortValue", sizeof(buf));
830         p.predicate = buf;
831         p.object = NULL;
832         q = lrdf_matches(&p);
833
834         p.predicate = NULL;
835         p.object = NULL;
836         for (i = q; i; i = i->next) {
837                 p.subject = i->object;
838                 lrdf_remove_matches(&p);
839         }
840
841         lrdf_free_statements(q);
842
843         p.subject = NULL;
844         strncpy(buf, LADSPA_BASE "hasSetting", sizeof(buf));
845         p.predicate = buf;
846         p.object = setting_uri_copy;
847         lrdf_remove_matches(&p);
848
849         p.subject = setting_uri_copy;
850         p.predicate = NULL;
851         p.object = NULL;
852         lrdf_remove_matches (&p);
853 }
854 #endif
855
856 void
857 LadspaPlugin::do_remove_preset (string name)
858 {
859 #ifdef HAVE_LRDF
860         string const envvar = preset_envvar ();
861         if (envvar.empty()) {
862                 warning << _("Could not locate HOME.  Preset not removed.") << endmsg;
863                 return;
864         }
865
866         Plugin::PresetRecord const * p = preset_by_label (name);
867         if (!p) {
868                 return;
869         }
870
871         string const source = preset_source (envvar);
872         lrdf_remove_preset (source.c_str(), p->uri.c_str ());
873
874         write_preset_file (envvar);
875 #endif
876 }
877
878 string
879 LadspaPlugin::preset_envvar () const
880 {
881         char* envvar;
882         if ((envvar = getenv ("HOME")) == 0) {
883                 return "";
884         }
885
886         return envvar;
887 }
888
889 string
890 LadspaPlugin::preset_source (string envvar) const
891 {
892         return string_compose ("file:%1/.ladspa/rdf/ardour-presets.n3", envvar);
893 }
894
895 bool
896 LadspaPlugin::write_preset_file (string envvar)
897 {
898 #ifdef HAVE_LRDF
899         string path = string_compose("%1/.ladspa", envvar);
900         if (g_mkdir_with_parents (path.c_str(), 0775)) {
901                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
902                 return false;
903         }
904
905         path += "/rdf";
906         if (g_mkdir_with_parents (path.c_str(), 0775)) {
907                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
908                 return false;
909         }
910
911         string const source = preset_source (envvar);
912
913         if (lrdf_export_by_source (source.c_str(), source.substr(5).c_str())) {
914                 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
915                 return false;
916         }
917
918         return true;
919 #else
920         return false;
921 #endif
922 }
923
924 string
925 LadspaPlugin::do_save_preset (string name)
926 {
927 #ifdef HAVE_LRDF
928         /* make a vector of pids that are input parameters */
929         vector<int> input_parameter_pids;
930         for (uint32_t i = 0; i < parameter_count(); ++i) {
931                 if (parameter_is_input (i)) {
932                         input_parameter_pids.push_back (i);
933                 }
934         }
935
936         std::string unique (unique_id());
937
938         if (!isdigit (unique[0])) {
939                 return "";
940         }
941
942         uint32_t const id = atol (unique.c_str());
943
944         lrdf_defaults defaults;
945         defaults.count = input_parameter_pids.size ();
946         std::vector<lrdf_portvalue> portvalues(input_parameter_pids.size());
947         defaults.items = &portvalues[0];
948
949         for (vector<int>::size_type i = 0; i < input_parameter_pids.size(); ++i) {
950                 portvalues[i].pid = input_parameter_pids[i];
951                 portvalues[i].value = get_parameter (input_parameter_pids[i]);
952         }
953
954         string const envvar = preset_envvar ();
955         if (envvar.empty()) {
956                 warning << _("Could not locate HOME.  Preset not saved.") << endmsg;
957                 return "";
958         }
959
960         string const source = preset_source (envvar);
961
962         char* uri_char = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults);
963         string uri (uri_char);
964         free (uri_char);
965
966         if (!write_preset_file (envvar)) {
967                 return "";
968         }
969
970         return uri;
971 #else
972         return string();
973 #endif
974 }
975
976 LADSPA_PortDescriptor
977 LadspaPlugin::port_descriptor (uint32_t i) const
978 {
979         if (i < _descriptor->PortCount) {
980                 return _descriptor->PortDescriptors[i];
981         }
982
983         warning << "LADSPA plugin port index " << i << " out of range." << endmsg;
984         return 0;
985 }
986
987
988