Remove LocaleGuards from ARDOUR::Tempo class
[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         LocaleGuard lg;
351
352         for (uint32_t i = 0; i < parameter_count(); ++i){
353
354                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
355                     LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
356
357                         child = new XMLNode("Port");
358                         child->set_property("number", i);
359                         child->set_property("value", _shadow_data[i]);
360                         root->add_child_nocopy (*child);
361                 }
362         }
363 }
364
365 int
366 LadspaPlugin::set_state (const XMLNode& node, int version)
367 {
368         if (version < 3000) {
369                 return set_state_2X (node, version);
370         }
371
372 #ifndef NO_PLUGIN_STATE
373         XMLNodeList nodes;
374         XMLNodeConstIterator iter;
375         XMLNode *child;
376 #endif
377         LocaleGuard lg;
378
379         if (node.name() != state_node_name()) {
380                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
381                 return -1;
382         }
383
384 #ifndef NO_PLUGIN_STATE
385
386         nodes = node.children ("Port");
387
388         for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
389
390                 child = *iter;
391
392                 uint32_t port_id;
393                 float value;
394
395                 if (!child->get_property ("number", port_id)) {
396                         warning << _("LADSPA: no ladspa port number") << endmsg;
397                         continue;
398                 }
399
400                 if (!child->get_property ("value", value)) {
401                         warning << _("LADSPA: no ladspa port data") << endmsg;
402                         continue;
403                 }
404
405                 set_parameter (port_id, value);
406         }
407 #endif
408
409         latency_compute_run ();
410
411         return Plugin::set_state (node, version);
412 }
413
414 int
415 LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */)
416 {
417 #ifndef NO_PLUGIN_STATE
418         XMLNodeList nodes;
419         XMLProperty const * prop;
420         XMLNodeConstIterator iter;
421         XMLNode *child;
422         const char *port;
423         const char *data;
424         uint32_t port_id;
425 #endif
426         LocaleGuard lg;
427
428         if (node.name() != state_node_name()) {
429                 error << _("Bad node sent to LadspaPlugin::set_state") << endmsg;
430                 return -1;
431         }
432
433 #ifndef NO_PLUGIN_STATE
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 #endif
459
460         return 0;
461 }
462
463 int
464 LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
465 {
466         LADSPA_PortRangeHint prh;
467
468         prh  = port_range_hints()[which];
469
470
471         if (LADSPA_IS_HINT_BOUNDED_BELOW(prh.HintDescriptor)) {
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.lower = 0;
479         }
480
481
482         if (LADSPA_IS_HINT_BOUNDED_ABOVE(prh.HintDescriptor)) {
483                 if (LADSPA_IS_HINT_SAMPLE_RATE(prh.HintDescriptor)) {
484                         desc.upper = prh.UpperBound * _session.frame_rate();
485                 } else {
486                         desc.upper = prh.UpperBound;
487                 }
488         } else {
489                 if (LADSPA_IS_HINT_TOGGLED (prh.HintDescriptor)) {
490                         desc.upper = 1;
491                 } else {
492                         desc.upper = 4; /* completely arbitrary */
493                 }
494         }
495
496         if (LADSPA_IS_HINT_HAS_DEFAULT (prh.HintDescriptor)) {
497                 desc.normal = _default_value(which);
498         } else {
499                 /* if there is no explicit hint for the default
500                  * value, use lower bound. This is not great but
501                  * better than just assuming '0' which may be out-of range.
502                  */
503                 desc.normal = desc.lower;
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         desc.scale_points = get_scale_points(which);
514         desc.update_steps();
515
516         return 0;
517 }
518
519 string
520 LadspaPlugin::describe_parameter (Evoral::Parameter which)
521 {
522         if (which.type() == PluginAutomation && which.id() < parameter_count()) {
523                 return port_names()[which.id()];
524         } else {
525                 return "??";
526         }
527 }
528
529 ARDOUR::framecnt_t
530 LadspaPlugin::signal_latency () const
531 {
532         if (_user_latency) {
533                 return _user_latency;
534         }
535
536         if (_latency_control_port) {
537                 return (framecnt_t) floor (*_latency_control_port);
538         } else {
539                 return 0;
540         }
541 }
542
543 set<Evoral::Parameter>
544 LadspaPlugin::automatable () const
545 {
546         set<Evoral::Parameter> ret;
547
548         for (uint32_t i = 0; i < parameter_count(); ++i){
549                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
550                     LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
551
552                         ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
553                 }
554         }
555
556         return ret;
557 }
558
559 int
560 LadspaPlugin::connect_and_run (BufferSet& bufs,
561                 framepos_t start, framepos_t end, double speed,
562                 ChanMapping in_map, ChanMapping out_map,
563                 pframes_t nframes, framecnt_t offset)
564 {
565         Plugin::connect_and_run (bufs, start, end, speed, in_map, out_map, nframes, offset);
566
567         cycles_t now;
568         cycles_t then = get_cycles ();
569
570         BufferSet& silent_bufs  = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1));
571         BufferSet& scratch_bufs = _session.get_scratch_buffers(ChanCount(DataType::AUDIO, 1));
572
573         uint32_t audio_in_index  = 0;
574         uint32_t audio_out_index = 0;
575         bool valid;
576         for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) {
577                 if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) {
578                         if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) {
579                                 const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
580                                 connect_port(port_index,
581                                              valid ? bufs.get_audio(buf_index).data(offset)
582                                                    : silent_bufs.get_audio(0).data(offset));
583                         } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) {
584                                 const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid);
585                                 connect_port(port_index,
586                                              valid ? bufs.get_audio(buf_index).data(offset)
587                                                    : scratch_bufs.get_audio(0).data(offset));
588                         }
589                 }
590         }
591
592         run_in_place (nframes);
593         now = get_cycles ();
594         set_cycles ((uint32_t) (now - then));
595
596         return 0;
597 }
598
599 bool
600 LadspaPlugin::parameter_is_control (uint32_t param) const
601 {
602         return LADSPA_IS_PORT_CONTROL(port_descriptor (param));
603 }
604
605 bool
606 LadspaPlugin::parameter_is_audio (uint32_t param) const
607 {
608         return LADSPA_IS_PORT_AUDIO(port_descriptor (param));
609 }
610
611 bool
612 LadspaPlugin::parameter_is_output (uint32_t param) const
613 {
614         return LADSPA_IS_PORT_OUTPUT(port_descriptor (param));
615 }
616
617 bool
618 LadspaPlugin::parameter_is_input (uint32_t param) const
619 {
620         return LADSPA_IS_PORT_INPUT(port_descriptor (param));
621 }
622
623 void
624 LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
625 {
626         if (buf && len) {
627                 if (param < parameter_count()) {
628                         snprintf (buf, len, "%.3f", get_parameter (param));
629                 } else {
630                         strcat (buf, "0");
631                 }
632         }
633 }
634
635 boost::shared_ptr<ScalePoints>
636 LadspaPlugin::get_scale_points(uint32_t port_index) const
637 {
638         boost::shared_ptr<ScalePoints> ret;
639 #ifdef HAVE_LRDF
640         const uint32_t id     = atol(unique_id().c_str());
641         lrdf_defaults* points = lrdf_get_scale_values(id, port_index);
642
643         if (!points) {
644                 return ret;
645         }
646
647         ret = boost::shared_ptr<ScalePoints>(new ScalePoints());
648
649         for (uint32_t i = 0; i < points->count; ++i) {
650                 ret->insert(make_pair(points->items[i].label,
651                                       points->items[i].value));
652         }
653
654         lrdf_free_setting_values(points);
655 #endif
656         return ret;
657 }
658
659 void
660 LadspaPlugin::run_in_place (pframes_t nframes)
661 {
662         for (uint32_t i = 0; i < parameter_count(); ++i) {
663                 if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
664                         _control_data[i] = _shadow_data[i];
665                 }
666         }
667
668         assert (_was_activated);
669
670         _descriptor->run (_handle, nframes);
671 }
672
673 void
674 LadspaPlugin::latency_compute_run ()
675 {
676         if (!_latency_control_port) {
677                 return;
678         }
679
680         /* we need to run the plugin so that it can set its latency
681            parameter.
682         */
683
684         activate ();
685
686         uint32_t port_index = 0;
687         uint32_t in_index = 0;
688         uint32_t out_index = 0;
689         const framecnt_t bufsize = 1024;
690         LADSPA_Data buffer[bufsize];
691
692         memset(buffer,0,sizeof(LADSPA_Data)*bufsize);
693
694         /* Note that we've already required that plugins
695            be able to handle in-place processing.
696         */
697
698         port_index = 0;
699
700         while (port_index < parameter_count()) {
701                 if (LADSPA_IS_PORT_AUDIO (port_descriptor (port_index))) {
702                         if (LADSPA_IS_PORT_INPUT (port_descriptor (port_index))) {
703                                 connect_port (port_index, buffer);
704                                 in_index++;
705                         } else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) {
706                                 connect_port (port_index, buffer);
707                                 out_index++;
708                         }
709                 }
710                 port_index++;
711         }
712
713         run_in_place (bufsize);
714         deactivate ();
715 }
716
717 PluginPtr
718 LadspaPluginInfo::load (Session& session)
719 {
720         try {
721                 PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate()));
722                 plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this)));
723                 return plugin;
724         }
725
726         catch (failed_constructor &err) {
727                 return PluginPtr ((Plugin*) 0);
728         }
729 }
730
731 std::vector<Plugin::PresetRecord>
732 LadspaPluginInfo::get_presets (bool /*user_only*/) const
733 {
734         std::vector<Plugin::PresetRecord> p;
735 #if (defined HAVE_LRDF && !defined NO_PLUGIN_STATE)
736         if (!isdigit (unique_id[0])) {
737                 return p;
738         }
739         uint32_t id = atol (unique_id);
740         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
741
742         if (set_uris) {
743                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
744                         if (char* label = lrdf_get_label (set_uris->items[i])) {
745                                 p.push_back (Plugin::PresetRecord (set_uris->items[i], label));
746                         }
747                 }
748                 lrdf_free_uris(set_uris);
749         }
750 #endif
751         return p;
752 }
753
754 LadspaPluginInfo::LadspaPluginInfo()
755 {
756        type = ARDOUR::LADSPA;
757 }
758
759
760 void
761 LadspaPlugin::find_presets ()
762 {
763 #ifdef HAVE_LRDF
764         uint32_t id;
765         std::string unique (unique_id());
766
767         if (!isdigit (unique[0])) {
768                 return;
769         }
770
771         id = atol (unique.c_str());
772
773         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
774
775         if (set_uris) {
776                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
777                         if (char* label = lrdf_get_label(set_uris->items[i])) {
778                                 PresetRecord rec (set_uris->items[i], label);
779                                 _presets.insert (make_pair (set_uris->items[i], rec));
780                         }
781                 }
782                 lrdf_free_uris(set_uris);
783         }
784 #endif
785 }
786
787
788 bool
789 LadspaPlugin::load_preset (PresetRecord r)
790 {
791 #ifdef HAVE_LRDF
792         lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str());
793
794         if (defs) {
795                 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
796                         if (parameter_is_input (defs->items[i].pid)) {
797                                 set_parameter(defs->items[i].pid, defs->items[i].value);
798                                 PresetPortSetValue (defs->items[i].pid, defs->items[i].value); /* EMIT SIGNAL */
799                         }
800                 }
801                 lrdf_free_setting_values(defs);
802         }
803
804         Plugin::load_preset (r);
805 #endif
806         return true;
807 }
808
809 #ifdef HAVE_LRDF
810 /* XXX: should be in liblrdf */
811 static void
812 lrdf_remove_preset (const char* /*source*/, const char *setting_uri)
813 {
814         lrdf_statement p;
815         lrdf_statement *q;
816         lrdf_statement *i;
817         char setting_uri_copy[64];
818         char buf[64];
819
820         strncpy(setting_uri_copy, setting_uri, sizeof(setting_uri_copy));
821
822         p.subject = setting_uri_copy;
823         strncpy(buf, LADSPA_BASE "hasPortValue", sizeof(buf));
824         p.predicate = buf;
825         p.object = NULL;
826         q = lrdf_matches(&p);
827
828         p.predicate = NULL;
829         p.object = NULL;
830         for (i = q; i; i = i->next) {
831                 p.subject = i->object;
832                 lrdf_remove_matches(&p);
833         }
834
835         lrdf_free_statements(q);
836
837         p.subject = NULL;
838         strncpy(buf, LADSPA_BASE "hasSetting", sizeof(buf));
839         p.predicate = buf;
840         p.object = setting_uri_copy;
841         lrdf_remove_matches(&p);
842
843         p.subject = setting_uri_copy;
844         p.predicate = NULL;
845         p.object = NULL;
846         lrdf_remove_matches (&p);
847 }
848 #endif
849
850 void
851 LadspaPlugin::do_remove_preset (string name)
852 {
853 #ifdef HAVE_LRDF
854         string const envvar = preset_envvar ();
855         if (envvar.empty()) {
856                 warning << _("Could not locate HOME.  Preset not removed.") << endmsg;
857                 return;
858         }
859
860         Plugin::PresetRecord const * p = preset_by_label (name);
861         if (!p) {
862                 return;
863         }
864
865         string const source = preset_source (envvar);
866         lrdf_remove_preset (source.c_str(), p->uri.c_str ());
867
868         write_preset_file (envvar);
869 #endif
870 }
871
872 string
873 LadspaPlugin::preset_envvar () const
874 {
875         char* envvar;
876         if ((envvar = getenv ("HOME")) == 0) {
877                 return "";
878         }
879
880         return envvar;
881 }
882
883 string
884 LadspaPlugin::preset_source (string envvar) const
885 {
886         return string_compose ("file:%1/.ladspa/rdf/ardour-presets.n3", envvar);
887 }
888
889 bool
890 LadspaPlugin::write_preset_file (string envvar)
891 {
892 #ifdef HAVE_LRDF
893         string path = string_compose("%1/.ladspa", envvar);
894         if (g_mkdir_with_parents (path.c_str(), 0775)) {
895                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
896                 return false;
897         }
898
899         path += "/rdf";
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         string const source = preset_source (envvar);
906
907         if (lrdf_export_by_source (source.c_str(), source.substr(5).c_str())) {
908                 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
909                 return false;
910         }
911
912         return true;
913 #else
914         return false;
915 #endif
916 }
917
918 string
919 LadspaPlugin::do_save_preset (string name)
920 {
921 #ifdef HAVE_LRDF
922         /* make a vector of pids that are input parameters */
923         vector<int> input_parameter_pids;
924         for (uint32_t i = 0; i < parameter_count(); ++i) {
925                 if (parameter_is_input (i)) {
926                         input_parameter_pids.push_back (i);
927                 }
928         }
929
930         std::string unique (unique_id());
931
932         if (!isdigit (unique[0])) {
933                 return "";
934         }
935
936         uint32_t const id = atol (unique.c_str());
937
938         lrdf_defaults defaults;
939         defaults.count = input_parameter_pids.size ();
940         std::vector<lrdf_portvalue> portvalues(input_parameter_pids.size());
941         defaults.items = &portvalues[0];
942
943         for (vector<int>::size_type i = 0; i < input_parameter_pids.size(); ++i) {
944                 portvalues[i].pid = input_parameter_pids[i];
945                 portvalues[i].value = get_parameter (input_parameter_pids[i]);
946         }
947
948         string const envvar = preset_envvar ();
949         if (envvar.empty()) {
950                 warning << _("Could not locate HOME.  Preset not saved.") << endmsg;
951                 return "";
952         }
953
954         string const source = preset_source (envvar);
955
956         char* uri_char = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults);
957         string uri (uri_char);
958         free (uri_char);
959
960         if (!write_preset_file (envvar)) {
961                 return "";
962         }
963
964         return uri;
965 #else
966         return string();
967 #endif
968 }
969
970 LADSPA_PortDescriptor
971 LadspaPlugin::port_descriptor (uint32_t i) const
972 {
973         if (i < _descriptor->PortCount) {
974                 return _descriptor->PortDescriptors[i];
975         }
976
977         warning << "LADSPA plugin port index " << i << " out of range." << endmsg;
978         return 0;
979 }
980
981
982