summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--src/state.c39
-rw-r--r--test/lilv_test.c12
-rw-r--r--test/test.lv2/test.c56
-rw-r--r--wscript4
5 files changed, 85 insertions, 32 deletions
diff --git a/NEWS b/NEWS
index 810b283..a7c43a8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+lilv (0.24.7) unstable;
+
+ * Implement state:freePath feature
+
+ -- David Robillard <d@drobilla.net> Sun, 08 Dec 2019 12:30:32 +0000
+
lilv (0.24.6) stable;
* Add more strict error detection when storing plugin state properties
diff --git a/src/state.c b/src/state.c
index ac1468c..23a659d 100644
--- a/src/state.c
+++ b/src/state.c
@@ -327,23 +327,34 @@ absolute_path(LV2_State_Map_Path_Handle handle,
return path;
}
-/** Return a new features array which is `feature` added to `features`. */
+/** Return a new features array with built-in features added to `features`. */
static const LV2_Feature**
-add_features(const LV2_Feature *const * features,
- const LV2_Feature* map, const LV2_Feature* make)
+add_features(const LV2_Feature* const* features,
+ const LV2_Feature* map,
+ const LV2_Feature* make,
+ const LV2_Feature* free)
{
size_t n_features = 0;
for (; features && features[n_features]; ++n_features) {}
const LV2_Feature** ret = (const LV2_Feature**)calloc(
- n_features + 3, sizeof(LV2_Feature*));
+ n_features + 4, sizeof(LV2_Feature*));
if (features) {
memcpy(ret, features, n_features * sizeof(LV2_Feature*));
}
- ret[n_features] = map;
- ret[n_features + 1] = make;
+ size_t i = n_features;
+ if (map) {
+ ret[i++] = map;
+ }
+ if (make) {
+ ret[i++] = make;
+ }
+ if (free) {
+ ret[i++] = free;
+ }
+
return ret;
}
@@ -369,6 +380,12 @@ state_strerror(LV2_State_Status st)
}
}
+static void
+lilv_free_path(LV2_State_Free_Path_Handle handle, char* path)
+{
+ lilv_free(path);
+}
+
LILV_API LilvState*
lilv_state_new_from_instance(const LilvPlugin* plugin,
LilvInstance* instance,
@@ -398,8 +415,11 @@ lilv_state_new_from_instance(const LilvPlugin* plugin,
LV2_Feature pmap_feature = { LV2_STATE__mapPath, &pmap };
LV2_State_Make_Path pmake = { state, make_path };
LV2_Feature pmake_feature = { LV2_STATE__makePath, &pmake };
+ LV2_State_Free_Path pfree = { NULL, lilv_free_path };
+ LV2_Feature pfree_feature = { LV2_STATE__freePath, &pfree };
features = sfeatures = add_features(features, &pmap_feature,
- save_dir ? &pmake_feature : NULL);
+ save_dir ? &pmake_feature : NULL,
+ &pfree_feature);
// Store port values
if (get_value) {
@@ -473,6 +493,9 @@ lilv_state_restore(const LilvState* state,
(LilvState*)state, abstract_path, absolute_path };
LV2_Feature map_feature = { LV2_STATE__mapPath, &map_path };
+ LV2_State_Free_Path free_path = { NULL, lilv_free_path };
+ LV2_Feature free_feature = { LV2_STATE__freePath, &free_path };
+
if (instance) {
const LV2_Descriptor* desc = instance->lv2_descriptor;
if (desc->extension_data) {
@@ -481,7 +504,7 @@ lilv_state_restore(const LilvState* state,
if (iface && iface->restore) {
const LV2_Feature** sfeatures = add_features(
- features, &map_feature, NULL);
+ features, &map_feature, NULL, &free_feature);
iface->restore(instance->lv2_handle, retrieve_callback,
(LV2_State_Handle)state, flags, sfeatures);
diff --git a/test/lilv_test.c b/test/lilv_test.c
index 7231c24..430187e 100644
--- a/test/lilv_test.c
+++ b/test/lilv_test.c
@@ -1572,6 +1572,12 @@ lilv_make_path(LV2_State_Make_Path_Handle handle,
return lilv_path_join(temp_dir, path);
}
+static void
+lilv_free_path(LV2_State_Free_Path_Handle handle, char* path)
+{
+ lilv_free(path);
+}
+
static int
test_state(void)
{
@@ -1768,7 +1774,11 @@ test_state(void)
LV2_State_Make_Path make_path = { NULL, lilv_make_path };
LV2_Feature make_path_feature = { LV2_STATE__makePath, &make_path };
- const LV2_Feature* ffeatures[] = { &make_path_feature, &map_feature, NULL };
+ LV2_State_Free_Path free_path = { NULL, lilv_free_path };
+ LV2_Feature free_path_feature = { LV2_STATE__freePath, &free_path };
+ const LV2_Feature* ffeatures[] = {
+ &make_path_feature, &map_feature, &free_path_feature, NULL
+ };
lilv_instance_deactivate(instance);
lilv_instance_free(instance);
diff --git a/test/test.lv2/test.c b/test/test.lv2/test.c
index d6802a6..fa3fb6e 100644
--- a/test/test.lv2/test.c
+++ b/test/test.lv2/test.c
@@ -43,7 +43,8 @@ enum {
};
typedef struct {
- LV2_URID_Map* map;
+ LV2_URID_Map* map;
+ LV2_State_Free_Path* free_path;
struct {
LV2_URID atom_Float;
@@ -59,23 +60,18 @@ typedef struct {
} Test;
static void
-free_path(char* path)
-{
- /* FIXME: Temporary hack to avoid mismatched malloc/free crashes on
- Windows. The specifications needs a feature for this. */
-#ifndef _WIN32
- free(path);
-#endif
-}
-
-static void
cleanup(LV2_Handle instance)
{
Test* test = (Test*)instance;
if (test->rec_file) {
fclose(test->rec_file);
}
- free_path(test->rec_file_path);
+
+ if (test->free_path) {
+ test->free_path->free_path(test->free_path->handle,
+ test->rec_file_path);
+ }
+
free(instance);
}
@@ -123,6 +119,8 @@ instantiate(const LV2_Descriptor* descriptor,
test->map->handle, LV2_ATOM__Float);
} else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) {
make_path = (LV2_State_Make_Path*)features[i]->data;
+ } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) {
+ test->free_path = (LV2_State_Free_Path*)features[i]->data;
}
}
@@ -133,6 +131,12 @@ instantiate(const LV2_Descriptor* descriptor,
}
if (make_path) {
+ if (!test->free_path) {
+ fprintf(stderr, "Host provided make_path without free_path\n");
+ free(test);
+ return NULL;
+ }
+
test->rec_file_path = make_path->path(make_path->handle, "recfile");
if (!(test->rec_file = fopen(test->rec_file_path, "w"))) {
fprintf(stderr, "ERROR: Failed to open rec file\n");
@@ -179,14 +183,21 @@ save(LV2_Handle instance,
LV2_State_Map_Path* map_path = NULL;
LV2_State_Make_Path* make_path = NULL;
+ LV2_State_Free_Path* free_path = NULL;
for (int i = 0; features && features[i]; ++i) {
if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) {
map_path = (LV2_State_Map_Path*)features[i]->data;
} else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) {
make_path = (LV2_State_Make_Path*)features[i]->data;
+ } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) {
+ free_path = (LV2_State_Free_Path*)features[i]->data;
}
}
+ if (!map_path || !free_path) {
+ return LV2_STATE_ERR_NO_FEATURE;
+ }
+
store(callback_data,
map_uri(plugin, "http://example.org/greeting"),
"hello",
@@ -281,8 +292,8 @@ save(LV2_Handle instance,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_POD);
- free_path(apath);
- free_path(apath2);
+ free_path->free_path(free_path->handle, apath);
+ free_path->free_path(free_path->handle, apath2);
if (plugin->rec_file) {
fflush(plugin->rec_file);
@@ -296,7 +307,7 @@ save(LV2_Handle instance,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_POD);
- free_path(apath);
+ free_path->free_path(free_path->handle, apath);
}
if (make_path) {
@@ -312,8 +323,8 @@ save(LV2_Handle instance,
strlen(apath) + 1,
map_uri(plugin, LV2_ATOM__Path),
LV2_STATE_IS_POD);
- free_path(apath);
- free_path(spath);
+ free_path->free_path(free_path->handle, apath);
+ free_path->free_path(free_path->handle, spath);
}
}
@@ -329,10 +340,13 @@ restore(LV2_Handle instance,
{
Test* plugin = (Test*)instance;
- LV2_State_Map_Path* map_path = NULL;
+ LV2_State_Map_Path* map_path = NULL;
+ LV2_State_Free_Path* free_path = NULL;
for (int i = 0; features && features[i]; ++i) {
if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) {
map_path = (LV2_State_Map_Path*)features[i]->data;
+ } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) {
+ free_path = (LV2_State_Free_Path*)features[i]->data;
}
}
@@ -345,7 +359,7 @@ restore(LV2_Handle instance,
map_uri(plugin, "http://example.org/num-runs"),
&size, &type, &valflags);
- if (!map_path) {
+ if (!map_path || !free_path) {
return LV2_STATE_ERR_NO_FEATURE;
}
@@ -369,7 +383,7 @@ restore(LV2_Handle instance,
fprintf(stderr, "error: Restored bad file contents `%s' != `Hello'\n",
str);
}
- free_path(path);
+ free_path->free_path(free_path->handle, path);
}
apath = (char*)retrieve(
@@ -384,7 +398,7 @@ restore(LV2_Handle instance,
} else {
fclose(sfile);
}
- free_path(spath);
+ free_path->free_path(free_path->handle, spath);
} else {
fprintf(stderr, "error: Failed to restore save file.\n");
}
diff --git a/wscript b/wscript
index 225ea30..4179dcd 100644
--- a/wscript
+++ b/wscript
@@ -12,7 +12,7 @@ from waflib.extras import autowaf
# major increment <=> incompatible changes
# minor increment <=> compatible changes (additions)
# micro increment <=> no interface changes
-LILV_VERSION = '0.24.6'
+LILV_VERSION = '0.24.7'
LILV_MAJOR_VERSION = '0'
# Mandatory waf variables
@@ -88,7 +88,7 @@ def configure(conf):
if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC:
conf.fatal('Neither a shared nor a static build requested')
- conf.check_pkg('lv2 >= 1.16.0', uselib_store='LV2')
+ conf.check_pkg('lv2 >= 1.17.0', uselib_store='LV2')
conf.check_pkg('serd-0 >= 0.30.0', uselib_store='SERD')
conf.check_pkg('sord-0 >= 0.14.0', uselib_store='SORD')
conf.check_pkg('sratom-0 >= 0.4.0', uselib_store='SRATOM')