X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fladspa_plugin.cc;h=3a25eab384b758292ddc16e9c444db69a4fda277;hb=f07ca6397f5699e4dc4ec1e360f9e263d8a0d9ad;hp=70a8390de1a4126a3f2c5df5cdabb925baadb6bb;hpb=bb9cc45cd22af67ac275a5e73accbe14fee664d8;p=ardour.git diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index 70a8390de1..3a25eab384 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -17,7 +17,6 @@ */ -#define __STDC_FORMAT_MACROS 1 #include #include @@ -54,7 +53,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, nframes_t rate) +LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) : Plugin (e, session) { init (mod, index, rate); @@ -72,7 +71,7 @@ LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) } void -LadspaPlugin::init (void *mod, uint32_t index, nframes_t rate) +LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) { LADSPA_Descriptor_Function dfunc; uint32_t i, port_cnt; @@ -144,8 +143,6 @@ LadspaPlugin::~LadspaPlugin () deactivate (); cleanup (); - GoingAway (); /* EMIT SIGNAL */ - /* XXX who should close a plugin? */ // dlclose (module); @@ -180,35 +177,18 @@ LadspaPlugin::default_value (uint32_t port) sr_scaling = true; } - /* FIXME: add support for logarithmic defaults */ - else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) { - if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) { - ret = exp(log(prh[port].LowerBound) * 0.75f + log(prh[port].UpperBound) * 0.25f); - } - else { - ret = prh[port].LowerBound * 0.75f + prh[port].UpperBound * 0.25f; - } + 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)) { - if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) { - ret = exp(log(prh[port].LowerBound) * 0.5f + log(prh[port].UpperBound) * 0.5f); - } - else { - ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f; - } + ret = prh[port].LowerBound * 0.5f + prh[port].UpperBound * 0.5f; bounds_given = true; sr_scaling = true; } else if (LADSPA_IS_HINT_DEFAULT_HIGH(prh[port].HintDescriptor)) { - if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) { - ret = exp(log(prh[port].LowerBound) * 0.25f + log(prh[port].UpperBound) * 0.75f); - } - else { - ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f; - } + ret = prh[port].LowerBound * 0.25f + prh[port].UpperBound * 0.75f; bounds_given = true; sr_scaling = true; } @@ -302,9 +282,8 @@ LadspaPlugin::set_parameter (uint32_t which, float val) { if (which < _descriptor->PortCount) { _shadow_data[which] = (LADSPA_Data) val; -#if 0 - ParameterChanged (Parameter(PluginAutomation, 0, which), val); /* EMIT SIGNAL */ +#if 0 if (which < parameter_count() && controls[which]) { controls[which]->Changed (); } @@ -316,8 +295,11 @@ LadspaPlugin::set_parameter (uint32_t which, float val) "invalid"), name()) << endmsg; } + + Plugin::set_parameter (which, val); } +/** @return `plugin' value */ float LadspaPlugin::get_parameter (uint32_t which) const { @@ -346,10 +328,9 @@ 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")); @@ -367,18 +348,59 @@ LadspaPlugin::get_state() 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; @@ -394,7 +416,7 @@ LadspaPlugin::set_state(const XMLNode& node) return -1; } - nodes = node.children ("Port"); + nodes = node.children ("port"); for(iter = nodes.begin(); iter != nodes.end(); ++iter){ @@ -486,7 +508,7 @@ LadspaPlugin::describe_parameter (Evoral::Parameter which) } } -ARDOUR::nframes_t +ARDOUR::framecnt_t LadspaPlugin::signal_latency () const { if (_user_latency) { @@ -494,7 +516,7 @@ LadspaPlugin::signal_latency () const } if (_latency_control_port) { - return (nframes_t) floor (*_latency_control_port); + return (framecnt_t) floor (*_latency_control_port); } else { return 0; } @@ -519,21 +541,31 @@ LadspaPlugin::automatable () const int LadspaPlugin::connect_and_run (BufferSet& bufs, ChanMapping in_map, ChanMapping out_map, - nframes_t nframes, nframes_t offset) + pframes_t nframes, framecnt_t offset) { + Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset); + cycles_t now; cycles_t then = get_cycles (); + BufferSet& silent_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1)); + BufferSet& scratch_bufs = _session.get_silent_buffers(ChanCount(DataType::AUDIO, 1)); + uint32_t audio_in_index = 0; uint32_t audio_out_index = 0; + bool valid; 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)); + const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++, &valid); + connect_port(port_index, + valid ? bufs.get_audio(buf_index).data(offset) + : silent_bufs.get_audio(0).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)); + const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++, &valid); + connect_port(port_index, + valid ? bufs.get_audio(buf_index).data(offset) + : scratch_bufs.get_audio(0).data(offset)); } } } @@ -581,14 +613,39 @@ 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_in_place (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]; } } + + assert (_was_activated); + _descriptor->run (_handle, nframes); } @@ -608,7 +665,7 @@ LadspaPlugin::latency_compute_run () uint32_t port_index = 0; uint32_t in_index = 0; uint32_t out_index = 0; - const nframes_t bufsize = 1024; + const framecnt_t bufsize = 1024; LADSPA_Data buffer[bufsize]; memset(buffer,0,sizeof(LADSPA_Data)*bufsize); @@ -646,6 +703,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())); } @@ -658,3 +716,216 @@ LadspaPluginInfo::load (Session& session) 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; +} + +LADSPA_PortDescriptor +LadspaPlugin::port_descriptor (uint32_t i) const +{ + if (i < _descriptor->PortCount) { + return _descriptor->PortDescriptors[i]; + } + + warning << "LADSPA plugin port index " << i << " out of range." << endmsg; + return 0; +} + + +