summaryrefslogtreecommitdiff
path: root/libs/ardour/lv2_plugin.cc
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-03-07 14:54:03 -0500
committerDavid Robillard <d@drobilla.net>2015-03-07 14:54:03 -0500
commitde078a04e23eae197565d231ea35362b5a7ee40e (patch)
tree4b92cc88c5c5d17df6724ea9d21f94cf24327fd6 /libs/ardour/lv2_plugin.cc
parent0cb096a9782bd13188e7add156af0a4c5e846e86 (diff)
Fix LV2 preset deletion and clash between plugins.
Before this, LV2 preset deletion in Ardour was doubly broken: the wrong file was being removed, and removing the correct file would only result in a broken preset. This change uses a new version of Lilv which has a more sophisticated mechanism for preset deletion. Also, fix "clashing" presets saved with the same name for different plugins, by prefixing the plugin name to the bundle (this is now a recommendation in the LV2 preset specification).
Diffstat (limited to 'libs/ardour/lv2_plugin.cc')
-rw-r--r--libs/ardour/lv2_plugin.cc43
1 files changed, 33 insertions, 10 deletions
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 7f744be3d6..d98f9a9ecc 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -1074,11 +1074,13 @@ ARDOUR::lv2plugin_get_port_value(const char* port_symbol,
std::string
LV2Plugin::do_save_preset(string name)
{
+ LilvNode* plug_name = lilv_plugin_get_name(_impl->plugin);
+ const string prefix = legalize_for_uri(lilv_node_as_string(plug_name));
const string base_name = legalize_for_uri(name);
const string file_name = base_name + ".ttl";
const string bundle = Glib::build_filename(
Glib::get_home_dir(),
- Glib::build_filename(".lv2", base_name + ".lv2"));
+ Glib::build_filename(".lv2", prefix + "_" + base_name + ".lv2"));
LilvState* state = lilv_state_new_from_instance(
_impl->plugin,
@@ -1110,7 +1112,7 @@ LV2Plugin::do_save_preset(string name)
std::string uri = Glib::filename_to_uri(Glib::build_filename(bundle, file_name));
LilvNode *node_bundle = lilv_new_uri(_world.world, Glib::filename_to_uri(Glib::build_filename(bundle, "/")).c_str());
LilvNode *node_preset = lilv_new_uri(_world.world, uri.c_str());
-#ifdef HAVE_LILV_0_19_2
+#ifdef HAVE_LILV_0_21_3
lilv_world_unload_resource(_world.world, node_preset);
lilv_world_unload_bundle(_world.world, node_bundle);
#endif
@@ -1118,20 +1120,41 @@ LV2Plugin::do_save_preset(string name)
lilv_world_load_resource(_world.world, node_preset);
lilv_node_free(node_bundle);
lilv_node_free(node_preset);
+ lilv_node_free(plug_name);
return uri;
}
void
LV2Plugin::do_remove_preset(string name)
{
- string preset_file = Glib::build_filename(
- Glib::get_home_dir(),
- Glib::build_filename(
- Glib::build_filename(".lv2", "presets"),
- name + ".ttl"
- )
- );
- ::g_unlink(preset_file.c_str());
+#ifdef HAVE_LILV_0_21_3
+ /* Look up preset record by label (FIXME: ick, label as ID) */
+ const PresetRecord* r = preset_by_label(name);
+ if (!r) {
+ return;
+ }
+
+ /* Load a LilvState for the preset. */
+ LilvWorld* world = _world.world;
+ LilvNode* pset = lilv_new_uri(world, r->uri.c_str());
+ LilvState* state = lilv_state_new_from_world(world, _uri_map.urid_map(), pset);
+ if (!state) {
+ lilv_node_free(pset);
+ return;
+ }
+
+ /* Delete it from the file system. This will remove the preset file and the entry
+ from the manifest. If this results in an empty manifest (i.e. the
+ preset is the only thing in the bundle), then the bundle is removed. */
+ lilv_state_delete(world, state);
+
+ lilv_state_free(state);
+ lilv_node_free(pset);
+#endif
+ /* Without lilv_state_delete(), we could delete the preset file, but this
+ would leave a broken bundle/manifest around, so the preset would still
+ be visible, but broken. Naively deleting a bundle is too dangerous, so
+ we simply do not support preset deletion with older Lilv */
}
bool