X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fladspa_plugin.cc;h=ef1a6b66823a8413cb540446425171351a0d2c94;hb=0938a42440cc82ce8d0cb064840c258c863714ab;hp=82cc4e620269e4e5bd7ec9588b0d1131cd615b39;hpb=82232f06ba3eea4a2b4342ad91fab552f4044402;p=ardour.git diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 82cc4e6202..ef1a6b6682 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2006 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,9 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ +#include + #include #include @@ -30,20 +31,20 @@ #include -#include -#include -#include -#include +#include "pbd/compose.h" +#include "pbd/error.h" +#include "pbd/xml++.h" -#include +#include "midi++/manager.h" -#include -#include -#include -#include -#include +#include "ardour/ardour.h" +#include "ardour/session.h" +#include "ardour/audioengine.h" +#include "ardour/ladspa_plugin.h" +#include "ardour/buffer_set.h" +#include "ardour/audio_buffer.h" -#include +#include "pbd/stl_delete.h" #include "i18n.h" #include @@ -52,7 +53,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, jack_nframes_t rate) +LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) : Plugin (e, session) { init (mod, index, rate); @@ -61,81 +62,79 @@ LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_ LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) : Plugin (other) { - init (other.module, other._index, other.sample_rate); + init (other._module, other._index, other._sample_rate); for (uint32_t i = 0; i < parameter_count(); ++i) { - control_data[i] = other.shadow_data[i]; - shadow_data[i] = other.shadow_data[i]; + _control_data[i] = other._shadow_data[i]; + _shadow_data[i] = other._shadow_data[i]; } } void -LadspaPlugin::init (void *mod, uint32_t index, jack_nframes_t rate) +LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) { LADSPA_Descriptor_Function dfunc; uint32_t i, port_cnt; const char *errstr; - module = mod; - control_data = 0; - shadow_data = 0; - latency_control_port = 0; - was_activated = false; + _module = mod; + _control_data = 0; + _shadow_data = 0; + _latency_control_port = 0; + _was_activated = false; - dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor"); + dfunc = (LADSPA_Descriptor_Function) dlsym (_module, "ladspa_descriptor"); if ((errstr = dlerror()) != NULL) { error << _("LADSPA: module has no descriptor function.") << endmsg; throw failed_constructor(); } - if ((descriptor = dfunc (index)) == 0) { + if ((_descriptor = dfunc (index)) == 0) { error << _("LADSPA: plugin has gone away since discovery!") << endmsg; throw failed_constructor(); } _index = index; - if (LADSPA_IS_INPLACE_BROKEN(descriptor->Properties)) { - error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), descriptor->Name) << endmsg; + if (LADSPA_IS_INPLACE_BROKEN(_descriptor->Properties)) { + error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), _descriptor->Name) << endmsg; throw failed_constructor(); } - - sample_rate = rate; - if (descriptor->instantiate == 0) { + _sample_rate = rate; + + if (_descriptor->instantiate == 0) { throw failed_constructor(); } - if ((handle = descriptor->instantiate (descriptor, rate)) == 0) { + if ((_handle = _descriptor->instantiate (_descriptor, rate)) == 0) { throw failed_constructor(); } port_cnt = parameter_count(); - control_data = new LADSPA_Data[port_cnt]; - shadow_data = new LADSPA_Data[port_cnt]; + _control_data = new LADSPA_Data[port_cnt]; + _shadow_data = new LADSPA_Data[port_cnt]; for (i = 0; i < port_cnt; ++i) { if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { - connect_port (i, &control_data[i]); - + connect_port (i, &_control_data[i]); + if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) && strcmp (port_names()[i], X_("latency")) == 0) { - latency_control_port = &control_data[i]; - *latency_control_port = 0; + _latency_control_port = &_control_data[i]; + *_latency_control_port = 0; } if (!LADSPA_IS_PORT_INPUT(port_descriptor (i))) { continue; } - - shadow_data[i] = default_value (i); + + _shadow_data[i] = default_value (i); } } - Plugin::setup_controls (); - latency_compute_run (); } @@ -144,46 +143,20 @@ LadspaPlugin::~LadspaPlugin () deactivate (); cleanup (); - GoingAway (); /* EMIT SIGNAL */ - /* XXX who should close a plugin? */ // dlclose (module); - if (control_data) { - delete [] control_data; - } - - if (shadow_data) { - delete [] shadow_data; - } -} - -void -LadspaPlugin::store_state (PluginState& state) -{ - state.parameters.clear (); - - for (uint32_t i = 0; i < parameter_count(); ++i){ - - if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && - LADSPA_IS_PORT_CONTROL(port_descriptor (i))){ - pair datum; - - datum.first = i; - datum.second = shadow_data[i]; - - state.parameters.insert (datum); - } - } + delete [] _control_data; + delete [] _shadow_data; } -void -LadspaPlugin::restore_state (PluginState& state) +string +LadspaPlugin::unique_id() const { - for (map::iterator i = state.parameters.begin(); i != state.parameters.end(); ++i) { - set_parameter (i->first, i->second); - } + char buf[32]; + snprintf (buf, sizeof (buf), "%lu", _descriptor->UniqueID); + return string (buf); } float @@ -193,25 +166,24 @@ LadspaPlugin::default_value (uint32_t port) float ret = 0.0f; bool bounds_given = false; bool sr_scaling = false; + bool earlier_hint = false; /* defaults - case 1 */ - + if (LADSPA_IS_HINT_HAS_DEFAULT(prh[port].HintDescriptor)) { if (LADSPA_IS_HINT_DEFAULT_MINIMUM(prh[port].HintDescriptor)) { ret = prh[port].LowerBound; bounds_given = true; sr_scaling = true; } - - /* FIXME: add support for logarithmic defaults */ - + else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) { ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f; bounds_given = true; sr_scaling = true; } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(prh[port].HintDescriptor)) { - ret = prh[port].LowerBound * 0.50f + prh[port].UpperBound * 0.50f; + ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f; bounds_given = true; sr_scaling = true; } @@ -227,26 +199,30 @@ LadspaPlugin::default_value (uint32_t port) } else if (LADSPA_IS_HINT_DEFAULT_0(prh[port].HintDescriptor)) { ret = 0.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_1(prh[port].HintDescriptor)) { ret = 1.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_100(prh[port].HintDescriptor)) { ret = 100.0f; + earlier_hint = true; } else if (LADSPA_IS_HINT_DEFAULT_440(prh[port].HintDescriptor)) { ret = 440.0f; + earlier_hint = true; } else { /* no hint found */ ret = 0.0f; } } - + /* defaults - case 2 */ else if (LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) && !LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) { - + if (prh[port].LowerBound < 0) { ret = 0.0f; } else { @@ -256,11 +232,11 @@ LadspaPlugin::default_value (uint32_t port) bounds_given = true; sr_scaling = true; } - + /* defaults - case 3 */ else if (!LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) && LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) { - + if (prh[port].UpperBound > 0) { ret = 0.0f; } else { @@ -270,11 +246,11 @@ LadspaPlugin::default_value (uint32_t port) bounds_given = true; sr_scaling = true; } - + /* defaults - case 4 */ else if (LADSPA_IS_HINT_BOUNDED_BELOW(prh[port].HintDescriptor) && LADSPA_IS_HINT_BOUNDED_ABOVE(prh[port].HintDescriptor)) { - + if (prh[port].LowerBound < 0 && prh[port].UpperBound > 0) { ret = 0.0f; } else if (prh[port].LowerBound < 0 && prh[port].UpperBound < 0) { @@ -282,51 +258,55 @@ LadspaPlugin::default_value (uint32_t port) } else { ret = prh[port].LowerBound; } - bounds_given = true; + bounds_given = true; sr_scaling = true; } - + /* defaults - case 5 */ - - if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor)) { + + if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) { if (bounds_given) { if (sr_scaling) { - ret *= sample_rate; + ret *= _sample_rate; } } else { - ret = sample_rate; + ret = _sample_rate; } } return ret; -} +} void LadspaPlugin::set_parameter (uint32_t which, float val) { - if (which < descriptor->PortCount) { - shadow_data[which] = (LADSPA_Data) val; - ParameterChanged (which, val); /* EMIT SIGNAL */ + if (which < _descriptor->PortCount) { + _shadow_data[which] = (LADSPA_Data) val; +#if 0 if (which < parameter_count() && controls[which]) { controls[which]->Changed (); } - +#endif + } else { warning << string_compose (_("illegal parameter number used with plugin \"%1\". This may" "indicate a change in the plugin design, and presets may be" "invalid"), name()) << endmsg; } + + Plugin::set_parameter (which, val); } +/** @return `plugin' value */ float LadspaPlugin::get_parameter (uint32_t which) const { if (LADSPA_IS_PORT_INPUT(port_descriptor (which))) { - return (float) shadow_data[which]; + return (float) _shadow_data[which]; } else { - return (float) control_data[which]; + return (float) _control_data[which]; } } @@ -337,7 +317,7 @@ LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const ok = false; - for (c = 0, x = 0; x < descriptor->PortCount; ++x) { + for (c = 0, x = 0; x < _descriptor->PortCount; ++x) { if (LADSPA_IS_PORT_CONTROL (port_descriptor (x))) { if (c++ == n) { ok = true; @@ -348,39 +328,79 @@ LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const return 0; } -XMLNode& -LadspaPlugin::get_state() +void +LadspaPlugin::add_state (XMLNode* root) const { - XMLNode *root = new XMLNode(state_node_name()); XMLNode *child; char buf[16]; LocaleGuard lg (X_("POSIX")); for (uint32_t i = 0; i < parameter_count(); ++i){ - if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && + if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))){ - child = new XMLNode("port"); + child = new XMLNode("Port"); snprintf(buf, sizeof(buf), "%u", i); child->add_property("number", string(buf)); - snprintf(buf, sizeof(buf), "%+f", shadow_data[i]); + snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]); child->add_property("value", string(buf)); root->add_child_nocopy (*child); } } - - return *root; } -bool -LadspaPlugin::save_preset (string name) +int +LadspaPlugin::set_state (const XMLNode& node, int version) { - return Plugin::save_preset (name, "ladspa"); + if (version < 3000) { + return set_state_2X (node, version); + } + + XMLNodeList nodes; + XMLProperty *prop; + XMLNodeConstIterator iter; + XMLNode *child; + const char *port; + const char *data; + uint32_t port_id; + LocaleGuard lg (X_("POSIX")); + + if (node.name() != state_node_name()) { + error << _("Bad node sent to LadspaPlugin::set_state") << endmsg; + return -1; + } + + nodes = node.children ("Port"); + + for (iter = nodes.begin(); iter != nodes.end(); ++iter) { + + child = *iter; + + if ((prop = child->property("number")) != 0) { + port = prop->value().c_str(); + } else { + warning << _("LADSPA: no ladspa port number") << endmsg; + continue; + } + if ((prop = child->property("value")) != 0) { + data = prop->value().c_str(); + } else { + warning << _("LADSPA: no ladspa port data") << endmsg; + continue; + } + + sscanf (port, "%" PRIu32, &port_id); + set_parameter (port_id, atof(data)); + } + + latency_compute_run (); + + return Plugin::set_state (node, version); } int -LadspaPlugin::set_state(const XMLNode& node) +LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */) { XMLNodeList nodes; XMLProperty *prop; @@ -430,7 +450,7 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des LADSPA_PortRangeHint prh; prh = port_range_hints()[which]; - + if (LADSPA_IS_HINT_BOUNDED_BELOW(prh.HintDescriptor)) { desc.min_unbound = false; @@ -443,7 +463,7 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.min_unbound = true; desc.lower = 0; } - + if (LADSPA_IS_HINT_BOUNDED_ABOVE(prh.HintDescriptor)) { desc.max_unbound = false; @@ -456,7 +476,7 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.max_unbound = true; desc.upper = 4; /* completely arbitrary */ } - + if (LADSPA_IS_HINT_INTEGER (prh.HintDescriptor)) { desc.step = 1.0; desc.smallstep = 0.1; @@ -467,7 +487,7 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.smallstep = delta / 10000.0f; desc.largestep = delta/10.0f; } - + desc.toggled = LADSPA_IS_HINT_TOGGLED (prh.HintDescriptor); desc.logarithmic = LADSPA_IS_HINT_LOGARITHMIC (prh.HintDescriptor); desc.sr_dependent = LADSPA_IS_HINT_SAMPLE_RATE (prh.HintDescriptor); @@ -475,41 +495,43 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.label = port_names()[which]; - return 0; } - string -LadspaPlugin::describe_parameter (uint32_t which) +LadspaPlugin::describe_parameter (Evoral::Parameter which) { - if (which < parameter_count()) { - return port_names()[which]; + if (which.type() == PluginAutomation && which.id() < parameter_count()) { + return port_names()[which.id()]; } else { return "??"; } } -jack_nframes_t -LadspaPlugin::latency () const +ARDOUR::framecnt_t +LadspaPlugin::signal_latency () const { - if (latency_control_port) { - return (jack_nframes_t) floor (*latency_control_port); + if (_user_latency) { + return _user_latency; + } + + if (_latency_control_port) { + return (framecnt_t) floor (*_latency_control_port); } else { return 0; } } -set +set LadspaPlugin::automatable () const { - set ret; + set ret; for (uint32_t i = 0; i < parameter_count(); ++i){ - if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && + if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))){ - - ret.insert (ret.end(), i); + + ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i)); } } @@ -517,37 +539,30 @@ LadspaPlugin::automatable () const } int -LadspaPlugin::connect_and_run (BufferSet& bufs, uint32_t& in_index, uint32_t& out_index, jack_nframes_t nframes, jack_nframes_t offset) +LadspaPlugin::connect_and_run (BufferSet& bufs, + ChanMapping in_map, ChanMapping out_map, + pframes_t nframes, framecnt_t offset) { - uint32_t port_index = 0; - cycles_t then, now; - - then = get_cycles (); - - const uint32_t nbufs = bufs.count().get(DataType::AUDIO); - - while (port_index < parameter_count()) { - if (LADSPA_IS_PORT_AUDIO (port_descriptor(port_index))) { - if (LADSPA_IS_PORT_INPUT (port_descriptor(port_index))) { - const size_t index = min(in_index, nbufs - 1); - connect_port (port_index, bufs.get_audio(index).data(nframes, offset)); - //cerr << this << ' ' << name() << " @ " << offset << " inport " << in_index << " = buf " - // << min((uint32_t)in_index,nbufs) << " = " << &bufs[min((uint32_t)in_index,nbufs)][offset] << endl; - in_index++; - - - } else if (LADSPA_IS_PORT_OUTPUT (port_descriptor (port_index))) { - const size_t index = min(out_index,nbufs - 1); - connect_port (port_index, bufs.get_audio(index).data(nframes, offset)); - // cerr << this << ' ' << name() << " @ " << offset << " outport " << out_index << " = buf " - // << min((uint32_t)out_index,nbufs) << " = " << &bufs[min((uint32_t)out_index,nbufs)][offset] << endl; - out_index++; + Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset); + + cycles_t now; + cycles_t then = get_cycles (); + + uint32_t audio_in_index = 0; + uint32_t audio_out_index = 0; + for (uint32_t port_index = 0; port_index < parameter_count(); ++port_index) { + if (LADSPA_IS_PORT_AUDIO(port_descriptor(port_index))) { + if (LADSPA_IS_PORT_INPUT(port_descriptor(port_index))) { + const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++); + connect_port(port_index, bufs.get_audio(buf_index).data(offset)); + } else if (LADSPA_IS_PORT_OUTPUT(port_descriptor(port_index))) { + const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++); + connect_port(port_index, bufs.get_audio(buf_index).data(offset)); } } - port_index++; } - - run (nframes); + + run_in_place (nframes); now = get_cycles (); set_cycles ((uint32_t) (now - then)); @@ -590,44 +605,69 @@ LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const } } +boost::shared_ptr +LadspaPlugin::get_scale_points(uint32_t port_index) const +{ + const uint32_t id = atol(unique_id().c_str()); + lrdf_defaults* points = lrdf_get_scale_values(id, port_index); + + boost::shared_ptr ret; + if (!points) { + return ret; + } + + ret = boost::shared_ptr(new ScalePoints()); + + for (uint32_t i = 0; i < points->count; ++i) { + ret->insert(make_pair(points->items[i].label, + points->items[i].value)); + } + + lrdf_free_setting_values(points); + return ret; +} + void -LadspaPlugin::run (jack_nframes_t nframes) +LadspaPlugin::run_in_place (pframes_t nframes) { for (uint32_t i = 0; i < parameter_count(); ++i) { if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { - control_data[i] = shadow_data[i]; + _control_data[i] = _shadow_data[i]; } } - descriptor->run (handle, nframes); + + assert (_was_activated); + + _descriptor->run (_handle, nframes); } void LadspaPlugin::latency_compute_run () { - if (!latency_control_port) { + if (!_latency_control_port) { return; } /* we need to run the plugin so that it can set its latency parameter. */ - + activate (); - + uint32_t port_index = 0; uint32_t in_index = 0; uint32_t out_index = 0; - const jack_nframes_t bufsize = 1024; + const framecnt_t bufsize = 1024; LADSPA_Data buffer[bufsize]; memset(buffer,0,sizeof(LADSPA_Data)*bufsize); - + /* Note that we've already required that plugins be able to handle in-place processing. */ - + port_index = 0; - + while (port_index < parameter_count()) { if (LADSPA_IS_PORT_AUDIO (port_descriptor (port_index))) { if (LADSPA_IS_PORT_INPUT (port_descriptor (port_index))) { @@ -640,8 +680,8 @@ LadspaPlugin::latency_compute_run () } port_index++; } - - run (bufsize); + + run_in_place (bufsize); deactivate (); } @@ -655,6 +695,7 @@ LadspaPluginInfo::load (Session& session) if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) { error << string_compose(_("LADSPA: cannot load module from \"%1\""), path) << endmsg; error << dlerror() << endmsg; + return PluginPtr ((Plugin*) 0); } else { plugin.reset (new LadspaPlugin (module, session.engine(), session, index, session.frame_rate())); } @@ -665,5 +706,205 @@ LadspaPluginInfo::load (Session& session) catch (failed_constructor &err) { return PluginPtr ((Plugin*) 0); - } + } +} + +LadspaPluginInfo::LadspaPluginInfo() +{ + type = ARDOUR::LADSPA; } + + +void +LadspaPlugin::find_presets () +{ + uint32_t id; + std::string unique (unique_id()); + + if (!isdigit (unique[0])) { + return; + } + + id = atol (unique.c_str()); + + lrdf_uris* set_uris = lrdf_get_setting_uris(id); + + if (set_uris) { + for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) { + if (char* label = lrdf_get_label(set_uris->items[i])) { + PresetRecord rec (set_uris->items[i], label); + _presets.insert (make_pair (set_uris->items[i], rec)); + } + } + lrdf_free_uris(set_uris); + } +} + + +bool +LadspaPlugin::load_preset (PresetRecord r) +{ + lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str()); + + if (defs) { + for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) { + if (parameter_is_input (defs->items[i].pid)) { + set_parameter(defs->items[i].pid, defs->items[i].value); + } + } + lrdf_free_setting_values(defs); + } + + Plugin::load_preset (r); + return true; +} + +/* XXX: should be in liblrdf */ +static void +lrdf_remove_preset (const char* /*source*/, const char *setting_uri) +{ + lrdf_statement p; + lrdf_statement *q; + lrdf_statement *i; + char setting_uri_copy[64]; + char buf[64]; + + strncpy(setting_uri_copy, setting_uri, sizeof(setting_uri_copy)); + + p.subject = setting_uri_copy; + strncpy(buf, LADSPA_BASE "hasPortValue", sizeof(buf)); + p.predicate = buf; + p.object = NULL; + q = lrdf_matches(&p); + + p.predicate = NULL; + p.object = NULL; + for (i = q; i; i = i->next) { + p.subject = i->object; + lrdf_remove_matches(&p); + } + + lrdf_free_statements(q); + + p.subject = NULL; + strncpy(buf, LADSPA_BASE "hasSetting", sizeof(buf)); + p.predicate = buf; + p.object = setting_uri_copy; + lrdf_remove_matches(&p); + + p.subject = setting_uri_copy; + p.predicate = NULL; + p.object = NULL; + lrdf_remove_matches (&p); +} + +void +LadspaPlugin::do_remove_preset (string name) +{ + string const envvar = preset_envvar (); + if (envvar.empty()) { + warning << _("Could not locate HOME. Preset not removed.") << endmsg; + return; + } + + Plugin::PresetRecord const * p = preset_by_label (name); + if (!p) { + return; + } + + string const source = preset_source (envvar); + lrdf_remove_preset (source.c_str(), p->uri.c_str ()); + + write_preset_file (envvar); +} + +string +LadspaPlugin::preset_envvar () const +{ + char* envvar; + if ((envvar = getenv ("HOME")) == 0) { + return ""; + } + + return envvar; +} + +string +LadspaPlugin::preset_source (string envvar) const +{ + return string_compose ("file:%1/.ladspa/rdf/ardour-presets.n3", envvar); +} + +bool +LadspaPlugin::write_preset_file (string envvar) +{ + string path = string_compose("%1/.ladspa", envvar); + if (g_mkdir_with_parents (path.c_str(), 0775)) { + warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg; + return false; + } + + path += "/rdf"; + if (g_mkdir_with_parents (path.c_str(), 0775)) { + warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg; + return false; + } + + string const source = preset_source (envvar); + + if (lrdf_export_by_source (source.c_str(), source.substr(5).c_str())) { + warning << string_compose(_("Error saving presets file %1."), source) << endmsg; + return false; + } + + return true; +} + +string +LadspaPlugin::do_save_preset (string name) +{ + /* make a vector of pids that are input parameters */ + vector input_parameter_pids; + for (uint32_t i = 0; i < parameter_count(); ++i) { + if (parameter_is_input (i)) { + input_parameter_pids.push_back (i); + } + } + + std::string unique (unique_id()); + + if (!isdigit (unique[0])) { + return ""; + } + + uint32_t const id = atol (unique.c_str()); + + lrdf_defaults defaults; + defaults.count = input_parameter_pids.size (); + lrdf_portvalue portvalues[input_parameter_pids.size()]; + defaults.items = portvalues; + + for (vector::size_type i = 0; i < input_parameter_pids.size(); ++i) { + portvalues[i].pid = input_parameter_pids[i]; + portvalues[i].value = get_parameter (input_parameter_pids[i]); + } + + string const envvar = preset_envvar (); + if (envvar.empty()) { + warning << _("Could not locate HOME. Preset not saved.") << endmsg; + return ""; + } + + string const source = preset_source (envvar); + + char* uri_char = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults); + string uri (uri_char); + free (uri_char); + + if (!write_preset_file (envvar)) { + return ""; + } + + return uri; +} +