diff --git a/SConstruct b/SConstruct index e2536c60ad..1b4bc349b3 100644 --- a/SConstruct +++ b/SConstruct @@ -594,12 +594,12 @@ else: if env['LV2']: conf = env.Configure(custom_tests = { 'CheckPKGVersion' : CheckPKGVersion}) - if conf.CheckPKGVersion('slv2', '0.6.2'): + if conf.CheckPKGVersion('slv2', '0.6.4'): libraries['slv2'] = LibraryInfo() libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2') env.Append (CCFLAGS="-DHAVE_LV2") else: - print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)' + print 'LV2 support is not enabled (SLV2 not found or older than 0.6.4 (svn))' env['LV2'] = 0 conf.Finish() else: diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index 336b7ea3df..eae0d91388 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -342,8 +342,8 @@ PlugUIBase::PlugUIBase (boost::shared_ptr pi) bypass_button (_("Bypass")), latency_gui (*pi, pi->session().frame_rate(), pi->session().get_block_size()) { - //preset_combo.set_use_arrows_always(true); - set_popdown_strings (preset_combo, plugin->get_presets()); + //preset_combo.set_use_arrows_always(true); + update_presets(); preset_combo.set_size_request (100, -1); preset_combo.set_active_text (""); preset_combo.signal_changed().connect(mem_fun(*this, &PlugUIBase::setting_selected)); @@ -389,8 +389,12 @@ void PlugUIBase::setting_selected() { if (preset_combo.get_active_text().length() > 0) { - if (!plugin->load_preset(preset_combo.get_active_text())) { - warning << string_compose(_("Plugin preset %1 not found"), preset_combo.get_active_text()) << endmsg; + const Plugin::PresetRecord* pr = plugin->preset_by_label(preset_combo.get_active_text()); + if (pr) { + plugin->load_preset(pr->uri); + } else { + warning << string_compose(_("Plugin preset %1 not found"), + preset_combo.get_active_text()) << endmsg; } } } @@ -408,14 +412,11 @@ PlugUIBase::save_plugin_setting () switch (prompter.run ()) { case Gtk::RESPONSE_ACCEPT: - string name; - prompter.get_result(name); - if (name.length()) { - if(plugin->save_preset(name)){ - set_popdown_strings (preset_combo, plugin->get_presets()); + if (plugin->save_preset(name)) { + update_presets(); preset_combo.set_active_text (name); } } @@ -460,5 +461,11 @@ PlugUIBase::focus_toggled (GdkEventButton* ev) void PlugUIBase::update_presets () { - set_popdown_strings (preset_combo, plugin->get_presets()); + vector preset_labels; + vector presets = plugin->get_presets(); + for (vector::const_iterator i = presets.begin(); + i != presets.end(); ++i) { + preset_labels.push_back(i->label); + } + set_popdown_strings (preset_combo, preset_labels); } diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h index 7114428626..bfc2be3ff1 100644 --- a/libs/ardour/ardour/lv2_plugin.h +++ b/libs/ardour/ardour/lv2_plugin.h @@ -109,7 +109,9 @@ class LV2Plugin : public ARDOUR::Plugin XMLNode& get_state(); int set_state(const XMLNode& node); - bool save_preset(std::string name); + bool save_preset(std::string uri); + bool load_preset(const string uri); + virtual std::vector get_presets(); bool has_editor() const; @@ -129,6 +131,7 @@ class LV2Plugin : public ARDOUR::Plugin float* _latency_control_port; bool _was_activated; vector _port_is_input; + map _port_indices; typedef struct { const void* (*extension_data)(const char* uri); } LV2_DataAccess; LV2_DataAccess _data_access_extension_data; diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index bb81776d53..68e94a9231 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -138,9 +138,19 @@ class Plugin : public PBD::StatefulDestructible, public Latent virtual bool parameter_is_input(uint32_t) const = 0; virtual bool parameter_is_output(uint32_t) const = 0; - virtual bool save_preset(string name) = 0; - virtual bool load_preset (const string preset_label); - virtual std::vector get_presets(); + virtual bool save_preset(string uri) = 0; + virtual bool load_preset (const string uri); + + struct PresetRecord { + PresetRecord(const std::string& u, const std::string& l) : uri(u), label(l) {} + string uri; + string label; + }; + + virtual std::vector get_presets(); + + const PresetRecord* preset_by_label(const string& label); + const PresetRecord* preset_by_uri(const string& uri); virtual bool has_editor() const = 0; @@ -189,8 +199,8 @@ class Plugin : public PBD::StatefulDestructible, public Latent ARDOUR::Session& _session; PluginInfoPtr _info; uint32_t _cycles; - map presets; - bool save_preset(string name, string domain /* vst, ladspa etc. */); + map presets; + bool save_preset(string uri, string domain /* vst, ladspa etc. */); }; PluginPtr find_plugin(ARDOUR::Session&, string unique_id, ARDOUR::PluginType); diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 16d5e390f8..4a432ba544 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -806,10 +806,10 @@ AUPlugin::load_preset (const string preset_label) return false; } -vector +vector AUPlugin::get_presets () { - vector presets; + vector presets; return presets; } diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 906edb3bda..03e3ea5bc2 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -119,8 +119,10 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, nframes_t rate) uint32_t latency_port = (latent ? slv2_plugin_get_latency_port_index(plugin) : 0); for (uint32_t i = 0; i < num_ports; ++i) { + SLV2Port port = slv2_plugin_get_port_by_index(plugin, i); + SLV2Value sym = slv2_port_get_symbol(_plugin, port); + _port_indices.insert(std::make_pair(slv2_value_as_string(sym), i)); if (parameter_is_control(i)) { - SLV2Port port = slv2_plugin_get_port_by_index(plugin, i); SLV2Value def; slv2_port_get_range(plugin, port, &def, NULL, NULL); _defaults[i] = def ? slv2_value_as_float(def) : 0.0f; @@ -274,10 +276,50 @@ LV2Plugin::get_state() return *root; } +vector +LV2Plugin::get_presets() +{ + vector result; + SLV2Results presets = slv2_plugin_query_sparql(_plugin, + "PREFIX lv2p: \n" + "PREFIX dc: \n" + "SELECT ?p ?name WHERE { <> lv2p:hasPreset ?p . ?p dc:title ?name }\n"); + for (; !slv2_results_finished(presets); slv2_results_next(presets)) { + SLV2Value uri = slv2_results_get_binding_value(presets, 0); + SLV2Value name = slv2_results_get_binding_value(presets, 1); + PresetRecord rec(slv2_value_as_string(uri), slv2_value_as_string(name)); + result.push_back(rec); + this->presets.insert(std::make_pair(slv2_value_as_string(uri), rec)); + } + slv2_results_free(presets); + return result; +} + +bool +LV2Plugin::load_preset(const string uri) +{ + const string query = string( + "PREFIX lv2p: \n" + "PREFIX dc: \n" + "SELECT ?sym ?val WHERE { <") + uri + "> lv2:port ?port . " + " ?port lv2:symbol ?sym ; lv2p:value ?val . }"; + SLV2Results values = slv2_plugin_query_sparql(_plugin, query.c_str()); + for (; !slv2_results_finished(values); slv2_results_next(values)) { + SLV2Value sym = slv2_results_get_binding_value(values, 0); + SLV2Value val = slv2_results_get_binding_value(values, 1); + if (slv2_value_is_float(val)) { + uint32_t index = _port_indices[slv2_value_as_string(sym)]; + set_parameter(index, slv2_value_as_float(val)); + } + } + slv2_results_free(values); + return true; +} + bool LV2Plugin::save_preset (string name) { - return Plugin::save_preset (name, "lv2"); + return false; } bool diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index c52a027915..8a08811e7e 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -70,10 +71,33 @@ Plugin::~Plugin () { } -vector +const Plugin::PresetRecord* +Plugin::preset_by_label(const string& label) +{ + // FIXME: O(n) + for (map::const_iterator i = presets.begin(); i != presets.end(); ++i) { + if (i->second.label == label) { + return &i->second; + } + } + return NULL; +} + +const Plugin::PresetRecord* +Plugin::preset_by_uri(const string& uri) +{ + map::const_iterator pr = presets.find(uri); + if (pr != presets.end()) { + return &pr->second; + } else { + return NULL; + } +} + +vector Plugin::get_presets() { - vector labels; + vector result; uint32_t id; std::string unique (unique_id()); @@ -83,7 +107,7 @@ Plugin::get_presets() */ if (!isdigit (unique[0])) { - return labels; + return result; } id = atol (unique.c_str()); @@ -93,23 +117,21 @@ Plugin::get_presets() 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])) { - labels.push_back(label); - presets[label] = set_uris->items[i]; + PresetRecord rec(set_uris->items[i], label); + result.push_back(rec); + presets.insert(std::make_pair(set_uris->items[i], rec)); } } lrdf_free_uris(set_uris); } - // GTK2FIX find an equivalent way to do this with a vector (needed by GUI apis) - // labels.unique(); - - return labels; + return result; } bool -Plugin::load_preset(const string preset_label) +Plugin::load_preset(const string preset_uri) { - lrdf_defaults* defs = lrdf_get_setting_values(presets[preset_label].c_str()); + lrdf_defaults* defs = lrdf_get_setting_values(preset_uri.c_str()); if (defs) { for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) { @@ -126,7 +148,7 @@ Plugin::load_preset(const string preset_label) } bool -Plugin::save_preset (string name, string domain) +Plugin::save_preset (string uri, string domain) { lrdf_portvalue portvalues[parameter_count()]; lrdf_defaults defaults; @@ -162,7 +184,12 @@ Plugin::save_preset (string name, string domain) string source(string_compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain)); - free(lrdf_add_preset(source.c_str(), name.c_str(), id, &defaults)); + map::const_iterator pr = presets.find(uri); + if (pr == presets.end()) { + warning << _("Could not find preset ") << uri << endmsg; + return false; + } + free(lrdf_add_preset(source.c_str(), pr->second.label.c_str(), id, &defaults)); string path = string_compose("%1/.%2", envvar, domain); if (g_mkdir_with_parents (path.c_str(), 0775)) {