summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-01-04 19:21:12 +0000
committerDavid Robillard <d@drobilla.net>2012-01-04 19:21:12 +0000
commit7823f743ee0c748ff4ced56838cd737516d857ab (patch)
tree083bcfd6edb27c53aa217da644f650e86f270070 /src
parent2f71e8570bcd37ad681bde7d51c433701a0028ab (diff)
downloadlilv-7823f743ee0c748ff4ced56838cd737516d857ab.tar.gz
lilv-7823f743ee0c748ff4ced56838cd737516d857ab.tar.bz2
lilv-7823f743ee0c748ff4ced56838cd737516d857ab.zip
Implement proper support for LV2_STATE_BUNDLE.
Test saving state to default bundle path. Fix memory leaks. git-svn-id: http://svn.drobilla.net/lad/trunk/lilv@3915 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/lilv_internal.h1
-rw-r--r--src/plugin.c17
-rw-r--r--src/state.c115
-rw-r--r--src/util.c39
-rw-r--r--src/world.c40
5 files changed, 128 insertions, 84 deletions
diff --git a/src/lilv_internal.h b/src/lilv_internal.h
index 9f19c1c..7191daa 100644
--- a/src/lilv_internal.h
+++ b/src/lilv_internal.h
@@ -330,6 +330,7 @@ LilvNodes* lilv_nodes_from_stream_objects(LilvWorld* w,
char* lilv_strjoin(const char* first, ...);
char* lilv_strdup(const char* str);
char* lilv_get_lang(void);
+char* lilv_expand(const char* path);
typedef void (*VoidFunc)(void);
diff --git a/src/plugin.c b/src/plugin.c
index 2a7ccee..2bb70c4 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -217,17 +217,20 @@ lilv_plugin_load_ports_if_necessary(const LilvPlugin* const_p)
LilvNode* symbol = lilv_plugin_get_unique(
p, port, p->world->lv2_symbol_node);
+ bool error = false;
if (!lilv_node_is_string(symbol) || !is_symbol(symbol->str_val)) {
LILV_ERRORF("Plugin <%s> port symbol `%s' is invalid\n",
lilv_node_as_uri(p->plugin_uri),
lilv_node_as_string(symbol));
- goto error;
+ error = true;
+ goto done;
}
if (!lilv_node_is_int(index)) {
LILV_ERRORF("Plugin <%s> port index is not an integer\n",
lilv_node_as_uri(p->plugin_uri));
- goto error;
+ error = true;
+ goto done;
}
uint32_t this_index = lilv_node_as_int(index);
@@ -265,13 +268,13 @@ lilv_plugin_load_ports_if_necessary(const LilvPlugin* const_p)
}
lilv_match_end(types);
- continue;
-
- error:
+ done:
lilv_node_free(symbol);
lilv_node_free(index);
- lilv_plugin_free_ports(p);
- break; // Invalid plugin
+ if (error) { // Invalid plugin
+ lilv_plugin_free_ports(p);
+ break;
+ }
}
lilv_match_end(ports);
diff --git a/src/state.c b/src/state.c
index c747937..05570cd 100644
--- a/src/state.c
+++ b/src/state.c
@@ -307,6 +307,7 @@ new_state_from_model(LilvWorld* world,
state->label = lilv_strdup(
(const char*)sord_node_get_string(lilv_match_object(i)));
sord_iter_free(i);
+ } else {
}
// Get port values
@@ -609,6 +610,70 @@ pathify(const char* in)
return out;
}
+static int
+mkdir_p(const char* dir_path)
+{
+ char* path = lilv_strdup(dir_path);
+ const size_t path_len = strlen(path);
+ for (size_t i = 1; i <= path_len; ++i) {
+ if (path[i] == LILV_DIR_SEP[0] || path[i] == '\0') {
+ path[i] = '\0';
+ if (mkdir(path, 0755) && errno != EEXIST) {
+ LILV_ERRORF("Failed to create %s (%s)\n",
+ path, strerror(errno));
+ free(path);
+ return 1;
+ }
+ path[i] = LILV_DIR_SEP[0];
+ }
+ }
+
+ free(path);
+ return 0;
+}
+
+static int
+lilv_default_state_path(LilvWorld* world,
+ const LilvState* state,
+ char** path,
+ char** manifest_path)
+{
+#ifdef HAVE_MKDIR
+ if (!state->label) {
+ LILV_ERROR("Attempt to save state with no label or path.\n");
+ return 1;
+ }
+
+ char* state_bundle = getenv("LV2_STATE_BUNDLE");
+ if (!state_bundle) {
+ state_bundle = LILV_DEFAULT_STATE_BUNDLE;
+ }
+
+ // Create ~/.lv2/presets.lv2/
+ char* const bundle = lilv_expand(state_bundle);
+ if (mkdir_p(bundle)) {
+ free(bundle);
+ return 3;
+ }
+
+ char* const filename = pathify(state->label);
+
+ *path = lilv_strjoin(
+ bundle, LILV_DIR_SEP, filename, ".ttl", NULL);
+
+ *manifest_path = lilv_strjoin(
+ bundle, LILV_DIR_SEP, "manifest.ttl", NULL);
+
+ free(bundle);
+ free(filename);
+
+ return 0;
+#else
+ LILV_ERROR("Save to default state path but mkdir is unavailable.\n");
+ return 4;
+#endif
+}
+
LILV_API
int
lilv_state_save(LilvWorld* world,
@@ -621,49 +686,13 @@ lilv_state_save(LilvWorld* world,
char* default_path = NULL;
char* default_manifest_path = NULL;
if (!path) {
-#ifdef HAVE_MKDIR
- if (!state->label) {
- LILV_ERROR("Attempt to save state with no label or path.\n");
+ if (lilv_default_state_path(
+ world, state, &default_path, &default_manifest_path)) {
return 1;
}
-
- const char* const home = getenv("HOME");
- if (!home) {
- LILV_ERROR("$HOME is undefined\n");
- return 2;
- }
-
- // Create ~/.lv2/
- char* const lv2dir = lilv_strjoin(home, "/.lv2/", NULL);
- if (mkdir(lv2dir, 0755) && errno != EEXIST) {
- LILV_ERRORF("Unable to create %s (%s)\n", lv2dir, strerror(errno));
- free(lv2dir);
- return 3;
- }
-
- // Create ~/.lv2/presets.lv2/
- char* const bundle = lilv_strjoin(lv2dir, "presets.lv2/", NULL);
- if (mkdir(bundle, 0755) && errno != EEXIST) {
- LILV_ERRORF("Unable to create %s (%s)\n", lv2dir, strerror(errno));
- free(lv2dir);
- free(bundle);
- return 4;
- }
-
- char* const filename = pathify(state->label);
- default_path = lilv_strjoin(bundle, filename, ".ttl", NULL);
- default_manifest_path = lilv_strjoin(bundle, "manifest.ttl", NULL);
-
+
path = default_path;
manifest_path = default_manifest_path;
-
- free(lv2dir);
- free(bundle);
- free(filename);
-#else
- LILV_ERROR("Save to default state path but mkdir is unavailable.\n");
- return 1;
-#endif
}
FILE* fd = fopen(path, "w");
@@ -779,6 +808,7 @@ lilv_state_save(LilvWorld* world,
serd_writer_write_statement(
writer, SERD_ANON_CONT, NULL,
&state_node, &p, &o, &t, NULL);
+ lilv_node_free(node);
} else {
char name[16];
snprintf(name, sizeof(name), "b%u", i);
@@ -835,6 +865,13 @@ void
lilv_state_free(LilvState* state)
{
if (state) {
+ for (uint32_t i = 0; i < state->num_props; ++i) {
+ free(state->props[i].value);
+ }
+ for (uint32_t i = 0; i < state->num_values; ++i) {
+ lilv_node_free(state->values[i].value);
+ free(state->values[i].symbol);
+ }
lilv_node_free(state->plugin_uri);
free(state->props);
free(state->values);
diff --git a/src/util.c b/src/util.c
index 0af0e1a..1c9a46e 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,6 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#define _POSIX_SOURCE 1 /* for wordexp */
+
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -21,6 +23,10 @@
#include "lilv_internal.h"
+#ifdef HAVE_WORDEXP
+# include <wordexp.h>
+#endif
+
char*
lilv_strjoin(const char* first, ...)
{
@@ -99,3 +105,36 @@ lilv_get_lang(void)
return lang;
}
+
+/** Expand variables (e.g. POSIX ~ or $FOO, Windows %FOO%) in @a path. */
+char*
+lilv_expand(const char* path)
+{
+#ifdef HAVE_WORDEXP
+ char* ret = NULL;
+ wordexp_t p;
+ if (wordexp(path, &p, 0)) {
+ LILV_ERRORF("Error expanding path `%s'\n", path);
+ return lilv_strdup(path);
+ }
+ if (p.we_wordc == 0) {
+ /* Literal directory path (e.g. no variables or ~) */
+ ret = lilv_strdup(path);
+ } else if (p.we_wordc == 1) {
+ /* Directory path expands (e.g. contains ~ or $FOO) */
+ ret = lilv_strdup(p.we_wordv[0]);
+ } else {
+ /* Multiple expansions in a single directory path? */
+ LILV_ERRORF("Malformed path `%s'\n", path);
+ ret = lilv_strdup(path);
+ }
+ wordfree(&p);
+#elif defined(__WIN32__)
+ static const size_t len = 32767;
+ char* ret = malloc(len);
+ ExpandEnvironmentStrings(path, ret, len);
+#else
+ char* ret = lilv_strdup(path);
+#endif
+ return ret;
+}
diff --git a/src/world.c b/src/world.c
index 2029136..8151a73 100644
--- a/src/world.c
+++ b/src/world.c
@@ -14,7 +14,7 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define _POSIX_SOURCE 1 /* for wordexp */
+#define _POSIX_SOURCE 1 /* for readdir_r */
#include <assert.h>
#include <errno.h>
@@ -25,10 +25,6 @@
#include "lilv_internal.h"
-#ifdef HAVE_WORDEXP
-# include <wordexp.h>
-#endif
-
LILV_API
LilvWorld*
lilv_world_new(void)
@@ -582,43 +578,11 @@ lilv_world_load_bundle(LilvWorld* world, LilvNode* bundle_uri)
serd_node_free(&manifest_uri);
}
-/** Expand variables (e.g. POSIX ~ or $FOO, Windows %FOO%) in @a path. */
-static char*
-expand(const char* path)
-{
-#ifdef HAVE_WORDEXP
- char* ret = NULL;
- wordexp_t p;
- if (wordexp(path, &p, 0)) {
- LILV_ERRORF("Error expanding path `%s'\n", path);
- return lilv_strdup(path);
- }
- if (p.we_wordc == 0) {
- /* Literal directory path (e.g. no variables or ~) */
- ret = lilv_strdup(path);
- } else if (p.we_wordc == 1) {
- /* Directory path expands (e.g. contains ~ or $FOO) */
- ret = lilv_strdup(p.we_wordv[0]);
- } else {
- /* Multiple expansions in a single directory path? */
- LILV_ERRORF("Malformed path `%s' ignored\n", path);
- }
- wordfree(&p);
-#elif defined(__WIN32__)
- static const size_t len = 32767;
- char* ret = malloc(len);
- ExpandEnvironmentStrings(path, ret, len);
-#else
- char* ret = lilv_strdup(path);
-#endif
- return ret;
-}
-
/** Load all bundles in the directory at @a dir_path. */
static void
lilv_world_load_directory(LilvWorld* world, const char* dir_path)
{
- char* path = expand(dir_path);
+ char* path = lilv_expand(dir_path);
if (!path) {
LILV_WARNF("Empty path `%s'\n", path);
return;