X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fladspa_plugin.cc;h=61149c78a01d61c81786aeddc9c2dede3f888560;hb=3c3d62c18a88c9a3ce8ae4d5f7a44470d302a1bf;hp=cab21f46f94f3cbabbeb7b01b8f7d16f94b8fe17;hpb=5f4bdb233a53932986e07fca1cd6c87d22c2886f;p=ardour.git diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc index cab21f46f9..61149c78a0 100644 --- a/libs/ardour/ladspa_plugin.cc +++ b/libs/ardour/ladspa_plugin.cc @@ -17,6 +17,10 @@ */ +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + #include #include @@ -25,21 +29,22 @@ #include #include // so libraptor doesn't complain #include +#ifndef COMPILER_MSVC #include +#endif #include #include +#ifdef HAVE_LRDF #include +#endif #include "pbd/compose.h" #include "pbd/error.h" #include "pbd/xml++.h" +#include "pbd/stacktrace.h" -#include "midi++/manager.h" - -#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" @@ -53,16 +58,16 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) +LadspaPlugin::LadspaPlugin (string module_path, AudioEngine& e, Session& session, uint32_t index, framecnt_t rate) : Plugin (e, session) { - init (mod, index, rate); + init (module_path, index, rate); } LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) : Plugin (other) { - init (other._module, other._index, other._sample_rate); + init (other._module_path, other._index, other._sample_rate); for (uint32_t i = 0; i < parameter_count(); ++i) { _control_data[i] = other._shadow_data[i]; @@ -71,25 +76,32 @@ LadspaPlugin::LadspaPlugin (const LadspaPlugin &other) } void -LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) +LadspaPlugin::init (string module_path, uint32_t index, framecnt_t rate) { + void* func; LADSPA_Descriptor_Function dfunc; uint32_t i, port_cnt; - const char *errstr; - _module = mod; + _module_path = module_path; + _module = new Glib::Module(_module_path); _control_data = 0; _shadow_data = 0; _latency_control_port = 0; _was_activated = false; - dfunc = (LADSPA_Descriptor_Function) dlsym (_module, "ladspa_descriptor"); + if (!(*_module)) { + error << _("LADSPA: Unable to open module: ") << Glib::Module::get_last_error() << endmsg; + delete _module; + throw failed_constructor(); + } - if ((errstr = dlerror()) != NULL) { + if (!_module->get_symbol("ladspa_descriptor", func)) { error << _("LADSPA: module has no descriptor function.") << endmsg; throw failed_constructor(); } + dfunc = (LADSPA_Descriptor_Function)func; + if ((_descriptor = dfunc (index)) == 0) { error << _("LADSPA: plugin has gone away since discovery!") << endmsg; throw failed_constructor(); @@ -115,7 +127,9 @@ LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) port_cnt = parameter_count(); _control_data = new LADSPA_Data[port_cnt]; + memset (_control_data, 0, sizeof (LADSPA_Data) * port_cnt); _shadow_data = new LADSPA_Data[port_cnt]; + memset (_shadow_data, 0, sizeof (LADSPA_Data) * port_cnt); for (i = 0; i < port_cnt; ++i) { if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) { @@ -131,7 +145,7 @@ LadspaPlugin::init (void *mod, uint32_t index, framecnt_t rate) continue; } - _shadow_data[i] = default_value (i); + _shadow_data[i] = _default_value (i); } } @@ -143,9 +157,8 @@ LadspaPlugin::~LadspaPlugin () deactivate (); cleanup (); - /* XXX who should close a plugin? */ - - // dlclose (module); + // glib has internal reference counting on modules so this is ok + delete _module; delete [] _control_data; delete [] _shadow_data; @@ -160,7 +173,7 @@ LadspaPlugin::unique_id() const } float -LadspaPlugin::default_value (uint32_t port) +LadspaPlugin::_default_value (uint32_t port) const { const LADSPA_PortRangeHint *prh = port_range_hints(); float ret = 0.0f; @@ -178,32 +191,17 @@ LadspaPlugin::default_value (uint32_t port) } 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; } @@ -296,17 +294,22 @@ void LadspaPlugin::set_parameter (uint32_t which, float val) { if (which < _descriptor->PortCount) { + + if (get_parameter (which) == val) { + return; + } + _shadow_data[which] = (LADSPA_Data) val; -#if 0 +#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" + 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; } @@ -314,6 +317,7 @@ LadspaPlugin::set_parameter (uint32_t which, float val) Plugin::set_parameter (which, val); } +/** @return `plugin' value */ float LadspaPlugin::get_parameter (uint32_t which) const { @@ -347,7 +351,7 @@ LadspaPlugin::add_state (XMLNode* root) const { XMLNode *child; char buf[16]; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg (X_("C")); for (uint32_t i = 0; i < parameter_count(); ++i){ @@ -371,6 +375,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version) return set_state_2X (node, version); } +#ifndef NO_PLUGIN_STATE XMLNodeList nodes; XMLProperty *prop; XMLNodeConstIterator iter; @@ -378,13 +383,16 @@ LadspaPlugin::set_state (const XMLNode& node, int version) const char *port; const char *data; uint32_t port_id; - LocaleGuard lg (X_("POSIX")); +#endif + LocaleGuard lg (X_("C")); if (node.name() != state_node_name()) { error << _("Bad node sent to LadspaPlugin::set_state") << endmsg; return -1; } +#ifndef NO_PLUGIN_STATE + nodes = node.children ("Port"); for (iter = nodes.begin(); iter != nodes.end(); ++iter) { @@ -407,6 +415,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version) sscanf (port, "%" PRIu32, &port_id); set_parameter (port_id, atof(data)); } +#endif latency_compute_run (); @@ -416,6 +425,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version) int LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */) { +#ifndef NO_PLUGIN_STATE XMLNodeList nodes; XMLProperty *prop; XMLNodeConstIterator iter; @@ -423,13 +433,15 @@ LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */) const char *port; const char *data; uint32_t port_id; - LocaleGuard lg (X_("POSIX")); +#endif + LocaleGuard lg (X_("C")); if (node.name() != state_node_name()) { error << _("Bad node sent to LadspaPlugin::set_state") << endmsg; return -1; } +#ifndef NO_PLUGIN_STATE nodes = node.children ("port"); for(iter = nodes.begin(); iter != nodes.end(); ++iter){ @@ -454,6 +466,7 @@ LadspaPlugin::set_state_2X (const XMLNode& node, int /* version */) } latency_compute_run (); +#endif return 0; } @@ -491,15 +504,14 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.upper = 4; /* completely arbitrary */ } - if (LADSPA_IS_HINT_INTEGER (prh.HintDescriptor)) { - desc.step = 1.0; - desc.smallstep = 0.1; - desc.largestep = 10.0; + if (LADSPA_IS_HINT_HAS_DEFAULT (prh.HintDescriptor)) { + desc.normal = _default_value(which); } else { - float delta = desc.upper - desc.lower; - desc.step = delta / 1000.0f; - desc.smallstep = delta / 10000.0f; - desc.largestep = delta/10.0f; + /* if there is no explicit hint for the default + * value, use lower bound. This is not great but + * better than just assuming '0' which may be out-of range. + */ + desc.normal = desc.lower; } desc.toggled = LADSPA_IS_HINT_TOGGLED (prh.HintDescriptor); @@ -509,6 +521,9 @@ LadspaPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& des desc.label = port_names()[which]; + desc.scale_points = get_scale_points(which); + desc.update_steps(); + return 0; } @@ -558,20 +573,28 @@ LadspaPlugin::connect_and_run (BufferSet& bufs, 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_scratch_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)); } } } @@ -619,6 +642,30 @@ LadspaPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const } } +boost::shared_ptr +LadspaPlugin::get_scale_points(uint32_t port_index) const +{ + boost::shared_ptr ret; +#ifdef HAVE_LRDF + const uint32_t id = atol(unique_id().c_str()); + lrdf_defaults* points = lrdf_get_scale_values(id, port_index); + + 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); +#endif + return ret; +} + void LadspaPlugin::run_in_place (pframes_t nframes) { @@ -629,7 +676,7 @@ LadspaPlugin::run_in_place (pframes_t nframes) } assert (_was_activated); - + _descriptor->run (_handle, nframes); } @@ -681,17 +728,7 @@ PluginPtr LadspaPluginInfo::load (Session& session) { try { - PluginPtr plugin; - void *module; - - 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())); - } - + PluginPtr plugin (new LadspaPlugin (path, session.engine(), session, index, session.frame_rate())); plugin->set_info(PluginInfoPtr(new LadspaPluginInfo(*this))); return plugin; } @@ -710,6 +747,7 @@ LadspaPluginInfo::LadspaPluginInfo() void LadspaPlugin::find_presets () { +#ifdef HAVE_LRDF uint32_t id; std::string unique (unique_id()); @@ -730,19 +768,19 @@ LadspaPlugin::find_presets () } lrdf_free_uris(set_uris); } +#endif } bool LadspaPlugin::load_preset (PresetRecord r) { +#ifdef HAVE_LRDF lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str()); if (defs) { for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) { - // The defs->items[i].pid < defs->count check is to work around - // a bug in liblrdf that saves invalid values into the presets file. - if (((uint32_t) defs->items[i].pid < (uint32_t) defs->count) && parameter_is_input (defs->items[i].pid)) { + if (parameter_is_input (defs->items[i].pid)) { set_parameter(defs->items[i].pid, defs->items[i].value); } } @@ -750,19 +788,21 @@ LadspaPlugin::load_preset (PresetRecord r) } Plugin::load_preset (r); +#endif return true; } +#ifdef HAVE_LRDF /* XXX: should be in liblrdf */ static void -lrdf_remove_preset (const char *source, const char *setting_uri) +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; @@ -791,10 +831,12 @@ lrdf_remove_preset (const char *source, const char *setting_uri) p.object = NULL; lrdf_remove_matches (&p); } +#endif void LadspaPlugin::do_remove_preset (string name) { +#ifdef HAVE_LRDF string const envvar = preset_envvar (); if (envvar.empty()) { warning << _("Could not locate HOME. Preset not removed.") << endmsg; @@ -805,11 +847,12 @@ LadspaPlugin::do_remove_preset (string name) if (!p) { return; } - + string const source = preset_source (envvar); lrdf_remove_preset (source.c_str(), p->uri.c_str ()); write_preset_file (envvar); +#endif } string @@ -819,7 +862,7 @@ LadspaPlugin::preset_envvar () const if ((envvar = getenv ("HOME")) == 0) { return ""; } - + return envvar; } @@ -832,6 +875,7 @@ LadspaPlugin::preset_source (string envvar) const bool LadspaPlugin::write_preset_file (string envvar) { +#ifdef HAVE_LRDF 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; @@ -852,13 +896,23 @@ LadspaPlugin::write_preset_file (string envvar) } return true; +#else + return false; +#endif } string LadspaPlugin::do_save_preset (string name) { - lrdf_portvalue portvalues[parameter_count()]; - lrdf_defaults defaults; +#ifdef HAVE_LRDF + /* 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])) { @@ -867,14 +921,14 @@ LadspaPlugin::do_save_preset (string name) uint32_t const id = atol (unique.c_str()); - defaults.count = parameter_count(); - defaults.items = portvalues; + lrdf_defaults defaults; + defaults.count = input_parameter_pids.size (); + std::vector portvalues(input_parameter_pids.size()); + defaults.items = &portvalues[0]; - for (uint32_t i = 0; i < parameter_count(); ++i) { - if (parameter_is_input (i)) { - portvalues[i].pid = i; - portvalues[i].value = get_parameter(i); - } + 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 (); @@ -894,5 +948,21 @@ LadspaPlugin::do_save_preset (string name) } return uri; +#else + return string(); +#endif } +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; +} + + +