aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-12-23 02:42:33 +0000
committerDavid Robillard <d@drobilla.net>2011-12-23 02:42:33 +0000
commite36a95bd35301c5343e593ef385f8b7573d9d606 (patch)
tree7f5d2243a970b4c85ca33ff0075259ba5e41d304 /src
parentbc8783a4b754296178da50805b275abcf5ff5738 (diff)
downloadjalv-e36a95bd35301c5343e593ef385f8b7573d9d606.tar.gz
jalv-e36a95bd35301c5343e593ef385f8b7573d9d606.tar.bz2
jalv-e36a95bd35301c5343e593ef385f8b7573d9d606.zip
Use new LilvState API for state/presets.
git-svn-id: http://svn.drobilla.net/lad/trunk/jalv@3900 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/jalv.c14
-rw-r--r--src/jalv_internal.h24
-rw-r--r--src/state.c650
3 files changed, 83 insertions, 605 deletions
diff --git a/src/jalv.c b/src/jalv.c
index 452094b..2bd6266 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -56,7 +56,7 @@ map_uri(LV2_URID_Map_Handle handle,
{
//return symap_map(((Jalv*)handle)->symap, uri);
const LV2_URID id = symap_map(((Jalv*)handle)->symap, uri);
- printf("MAP %s => %u\n", uri, id);
+ //printf("MAP %s => %u\n", uri, id);
return id;
}
@@ -77,7 +77,7 @@ uri_to_id(LV2_URI_Map_Callback_Data callback_data,
{
//return symap_map(((Jalv*)callback_data)->symap, uri);
const LV2_URID id = symap_map(((Jalv*)callback_data)->symap, uri);
- printf("MAP %s => %u\n", uri, id);
+ //printf("MAP %s => %u\n", uri, id);
return id;
}
@@ -563,15 +563,17 @@ main(int argc, char** argv)
"connectionOptional");
/* Get plugin URI from loaded state or command line */
- PluginState* state = NULL;
- LilvNode* plugin_uri = NULL;
+ LilvState* state = NULL;
+ LilvNode* plugin_uri = NULL;
if (host.opts.load) {
- state = jalv_load_state(&host, host.opts.load);
+ char* path = jalv_strjoin(host.opts.load, "/state.ttl");
+ state = lilv_state_new_from_file(host.world, &host.map, NULL, path);
+ free(path);
if (!state) {
fprintf(stderr, "Failed to load state from %s\n", host.opts.load);
return EXIT_FAILURE;
}
- plugin_uri = lilv_node_duplicate(plugin_state_get_plugin_uri(state));
+ plugin_uri = lilv_node_duplicate(lilv_state_get_plugin_uri(state));
} else if (argc > 1) {
plugin_uri = lilv_new_uri(world, argv[1]);
} else {
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index d5f29f5..e4f65ec 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -63,11 +63,6 @@ struct Port {
bool old_api; /**< True for event, false for atom */
};
-typedef struct PluginStateImpl PluginState;
-
-const LilvNode*
-plugin_state_get_plugin_uri(const PluginState* state);
-
/**
Control change event, sent through ring buffers for UI updates.
*/
@@ -173,11 +168,8 @@ jalv_save_port_values(Jalv* jalv,
SerdWriter* writer,
const SerdNode* subject);
-PluginState*
-jalv_load_state(Jalv* jalv, const char* dir);
-
void
-jalv_apply_state(Jalv* jalv, PluginState* state);
+jalv_apply_state(Jalv* jalv, LilvState* state);
static inline char*
jalv_strdup(const char* str)
@@ -188,6 +180,20 @@ jalv_strdup(const char* str)
return copy;
}
+static inline char*
+jalv_strjoin(const char* a, const char* b)
+{
+ const size_t a_len = strlen(a);
+ const size_t b_len = strlen(b);
+ char* const out = (char*)malloc(a_len + b_len + 1);
+
+ memcpy(out, a, a_len);
+ memcpy(out + a_len, b, b_len);
+ out[a_len + b_len] = '\0';
+
+ return out;
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/src/state.c b/src/state.c
index 9f3282e..5edab41 100644
--- a/src/state.c
+++ b/src/state.c
@@ -34,10 +34,6 @@
#include "jalv-config.h"
#include "jalv_internal.h"
-#ifdef HAVE_LOCKF
-#include <unistd.h>
-#endif
-
#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
#define NS_JALV "http://drobilla.net/ns/jalv#"
#define NS_LV2 "http://lv2plug.in/ns/lv2core#"
@@ -49,382 +45,30 @@
#define USTR(s) ((const uint8_t*)s)
-typedef struct {
- uint32_t key;
- SerdNode value;
- SerdNode datatype;
-} Property;
-
-typedef struct {
- SerdNode symbol;
- SerdNode value;
- SerdNode datatype;
-} PortValue;
-
-struct PluginStateImpl {
- LilvNode* plugin_uri;
- Property* props;
- PortValue* values;
- uint32_t num_props;
- uint32_t num_values;
-};
-
-const LilvNode*
-plugin_state_get_plugin_uri(const PluginState* state)
-{
- return state->plugin_uri;
-}
-
-static int
-property_cmp(const void* a, const void* b)
-{
- const Property* pa = (const Property*)a;
- const Property* pb = (const Property*)b;
- return pa->key - pb->key;
-}
-
-static int
-value_cmp(const void* a, const void* b)
+LilvNode*
+get_port_value(const char* port_symbol,
+ void* user_data)
{
- const PortValue* pa = (const PortValue*)a;
- const PortValue* pb = (const PortValue*)b;
- return strcmp((const char*)pa->symbol.buf, (const char*)pb->symbol.buf);
-}
-
-static char*
-strjoin(const char* a, const char* b)
-{
- const size_t a_len = strlen(a);
- const size_t b_len = strlen(b);
- char* const out = malloc(a_len + b_len + 1);
-
- memcpy(out, a, a_len);
- memcpy(out + a_len, b, b_len);
- out[a_len + b_len] = '\0';
-
- return out;
-}
-
-#ifdef HAVE_LV2_STATE
-typedef struct {
- LV2_URID_Unmap* unmap;
- const SerdNode* subject;
- SerdWriter* writer;
-} StoreData;
-
-static int
-store_callback(void* handle,
- uint32_t key,
- const void* value,
- size_t size,
- uint32_t type,
- uint32_t flags)
-{
- StoreData* data = (StoreData*)handle;
- const char* key_uri = data->unmap->unmap(data->unmap->handle, key);
- const char* type_uri = data->unmap->unmap(data->unmap->handle, type);
- if (strcmp(type_uri, (const char*)(NS_ATOM "String"))) {
- fprintf(stderr, "error: Unsupported (not atom:String) value stored\n");
- return 1;
- }
-
- if (key_uri && type_uri && value) {
- const SerdNode p = serd_node_from_string(SERD_URI, USTR(key_uri));
- const SerdNode o = serd_node_from_string(SERD_LITERAL, USTR(value));
- const SerdNode t = serd_node_from_string(SERD_URI, USTR(type_uri));
-
- serd_writer_write_statement(data->writer, SERD_ANON_CONT, NULL,
- data->subject, &p, &o, &t, NULL);
-
- return 0;
+ Jalv* jalv = (Jalv*)user_data;
+ struct Port* port = jalv_port_by_symbol(jalv, port_symbol);
+ if (port && port->flow == FLOW_INPUT && port->type == TYPE_CONTROL) {
+ return lilv_new_float(jalv->world, port->control);
}
-
- fprintf(stderr, "error: Failed to store property (key %d)\n", key);
- return 1;
-}
-
-typedef struct {
- LV2_URID_Map* map;
- const Property* props;
- const uint32_t num_props;
-} RetrieveData;
-
-static const void*
-retrieve_callback(void* handle,
- uint32_t key,
- size_t* size,
- uint32_t* type,
- uint32_t* flags)
-{
- RetrieveData* data = (RetrieveData*)handle;
- Property search_key = { key, SERD_NODE_NULL, SERD_NODE_NULL };
- Property* prop = (Property*)bsearch(
- &search_key, data->props, data->num_props,
- sizeof(Property), property_cmp);
-
- if (prop) {
- *size = prop->value.n_bytes;
- *type = data->map->map(data->map->handle,
- (const char*)(NS_ATOM "String"));
- *flags = 0;
- return prop->value.buf;
- }
-
return NULL;
-
-}
-#endif // HAVE_LV2_STATE
-
-static size_t
-file_sink(const void* buf, size_t len, void* stream)
-{
- FILE* file = (FILE*)stream;
- return fwrite(buf, 1, len, file);
-}
-
-int
-write_preset(Jalv* jalv, const char* path, const char* label)
-{
- FILE* fd = fopen(path, "w");
- if (!fd) {
- fprintf(stderr, "error: Failed to open %s (%s)\n",
- path, strerror(errno));
- return 1;
- }
-
- SerdEnv* env = serd_env_new(NULL);
- serd_env_set_prefix_from_strings(env, USTR("atom"), USTR(NS_ATOM));
- serd_env_set_prefix_from_strings(env, USTR("jalv"), USTR(NS_JALV));
- serd_env_set_prefix_from_strings(env, USTR("lv2"), USTR(NS_LV2));
- serd_env_set_prefix_from_strings(env, USTR("pset"), USTR(NS_PSET));
- serd_env_set_prefix_from_strings(env, USTR("rdfs"), USTR(NS_RDFS));
- serd_env_set_prefix_from_strings(env, USTR("state"), USTR(NS_STATE));
-
- SerdNode lv2_appliesTo = serd_node_from_string(
- SERD_CURIE, USTR("lv2:appliesTo"));
-
- SerdNode plugin_uri = serd_node_from_string(SERD_URI, USTR(lilv_node_as_uri(
- lilv_plugin_get_uri(jalv->plugin))));
-
- SerdNode subject = serd_node_from_string(SERD_URI, USTR(""));
-
- SerdWriter* writer = serd_writer_new(
- SERD_TURTLE,
- SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED,
- env,
- &SERD_URI_NULL,
- file_sink,
- fd);
-
- serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, writer);
-
- // subject a pset:Preset
- SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "type"));
- SerdNode o = serd_node_from_string(SERD_CURIE, USTR("pset:Preset"));
- serd_writer_write_statement(writer, 0, NULL,
- &subject, &p, &o, NULL, NULL);
-
- // subject lv2:appliesTo <http://example.org/plugin>
- serd_writer_write_statement(writer, 0, NULL,
- &subject,
- &lv2_appliesTo,
- &plugin_uri, NULL, NULL);
-
- // subject rdfs:label label
- if (label) {
- p = serd_node_from_string(SERD_URI, USTR(NS_RDFS "label"));
- o = serd_node_from_string(SERD_LITERAL, USTR(label));
- serd_writer_write_statement(writer, 0,
- NULL, &subject, &p, &o, NULL, NULL);
- }
-
- jalv_save_port_values(jalv, writer, &subject);
-
-#ifdef HAVE_LV2_STATE
- assert(jalv->symap);
- const LV2_State_Interface* state = (const LV2_State_Interface*)
- lilv_instance_get_extension_data(jalv->instance, LV2_STATE_INTERFACE_URI);
-
- if (state) {
- SerdNode state_instanceState = serd_node_from_string(
- SERD_URI, USTR(NS_STATE "instanceState"));
-
- // subject state:instanceState [
- SerdNode state_node = serd_node_from_string(SERD_BLANK, USTR("state"));
- serd_writer_write_statement(writer, SERD_ANON_O_BEGIN, NULL,
- &subject,
- &state_instanceState,
- &state_node, NULL, NULL);
-
- StoreData data = { &jalv->unmap, &state_node, writer };
-
- // Write properties to state blank node
- state->save(lilv_instance_get_handle(jalv->instance),
- store_callback,
- &data,
- LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE,
- NULL);
-
- // ]
- serd_writer_end_anon(writer, &state_node);
- }
-#endif // HAVE_LV2_STATE
-
- // Close state file and clean up Serd
- serd_writer_free(writer);
- fclose(fd);
- serd_env_free(env);
-
- return 0;
}
void
jalv_save(Jalv* jalv, const char* dir)
{
- char* const path = strjoin(dir, "/state.ttl");
- write_preset(jalv, path, NULL);
- free(path);
-}
-
-typedef struct {
- LilvWorld* world;
- LV2_URID_Map* map;
- LilvNode* plugin_uri;
- Property* props;
- PortValue* ports;
- uint32_t num_props;
- uint32_t num_ports;
- bool in_state;
-} RestoreData;
-
-static SerdStatus
-on_statement(void* handle,
- SerdStatementFlags flags,
- const SerdNode* graph,
- const SerdNode* subject,
- const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* object_datatype,
- const SerdNode* object_lang)
-{
- RestoreData* data = (RestoreData*)handle;
- if (data->in_state) {
- data->props = (Property*)realloc(
- data->props, sizeof(Property) * (++data->num_props));
- Property* prop = &data->props[data->num_props - 1];
- prop->key = data->map->map(data->map->handle,
- (const char*)predicate->buf);
- prop->value = serd_node_copy(object);
- prop->datatype = serd_node_copy(object_datatype);
- } else if (!strcmp((const char*)predicate->buf, "lv2:appliesTo")) {
- data->plugin_uri = lilv_new_uri(data->world, (const char*)object->buf);
- } else if (!strcmp((const char*)predicate->buf, "lv2:port")) {
- data->ports = (PortValue*)realloc(
- data->ports, sizeof(PortValue) * (++data->num_ports));
- data->ports[data->num_ports - 1].symbol = SERD_NODE_NULL;
- data->ports[data->num_ports - 1].value = SERD_NODE_NULL;
- data->ports[data->num_ports - 1].datatype = SERD_NODE_NULL;
- } else if (!strcmp((const char*)predicate->buf, "lv2:symbol")) {
- data->ports[data->num_ports - 1].symbol = serd_node_copy(object);
- } else if (!strcmp((const char*)predicate->buf, "pset:value")) {
- data->ports[data->num_ports - 1].value = serd_node_copy(object);
- data->ports[data->num_ports - 1].datatype = serd_node_copy(object_datatype);
- } else if (!strcmp((const char*)predicate->buf, "state:instanceState")) {
- data->in_state = true;
- }
-
- return SERD_SUCCESS;
-}
-
-static PluginState*
-load_state_from_file(LilvWorld* world,
- LV2_URID_Map* map,
- const char* state_uri);
-
-PluginState*
-jalv_load_state(Jalv* jalv, const char* dir)
-{
- char* base_uri = strjoin("file://", dir);
- char* state_uri = strjoin(base_uri, "/state.ttl");
-
- PluginState* state = load_state_from_file(
- jalv->world, &jalv->map, state_uri);
-
- free(state_uri);
- free(base_uri);
- return state;
-}
-
-static PluginState*
-load_state_from_file(LilvWorld* world,
- LV2_URID_Map* map,
- const char* state_uri)
-{
- RestoreData data;
- memset(&data, '\0', sizeof(RestoreData));
- data.world = world;
- data.map = map;
-
- SerdReader* reader = serd_reader_new(
- SERD_TURTLE,
- &data, NULL,
- NULL,
- NULL,
- on_statement,
- NULL);
-
- SerdStatus st = serd_reader_read_file(reader, USTR(state_uri));
- if (st) {
- fprintf(stderr, "Error reading state from %s (%s)\n",
- state_uri, serd_strerror(st));
- return NULL;
- }
-
- serd_reader_free(reader);
-
- PluginState* state = (PluginState*)malloc(sizeof(PluginState));
- state->plugin_uri = data.plugin_uri;
- state->props = data.props;
- state->num_props = data.num_props;
- state->values = data.ports;
- state->num_values = data.num_ports;
-
- if (state->props) {
- qsort(state->props, state->num_props, sizeof(Property), property_cmp);
- }
- if (state->values) {
- qsort(state->values, state->num_values, sizeof(PortValue), value_cmp);
- }
-
- return state;
-}
-
-void
-jalv_apply_state(Jalv* jalv, PluginState* state)
-{
- /* Set port values */
- for (uint32_t i = 0; i < state->num_values; ++i) {
- PortValue* dport = &state->values[i];
- const char* sym = (const char*)dport->symbol.buf;
- struct Port* const jport = jalv_port_by_symbol(jalv, sym);
- if (jport) {
- jport->control = atof((const char*)dport->value.buf); // FIXME: Check type
- } else {
- fprintf(stderr, "error: Failed to find port `%s'\n", sym);
- }
- }
+ char* const path = jalv_strjoin(dir, "/state.ttl");
+ LilvState* const state = lilv_state_new_from_instance(
+ jalv->plugin, jalv->instance,
+ get_port_value, jalv,
+ LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE, NULL);
-#ifdef HAVE_LV2_STATE
- const LV2_State_Interface* state_iface = (const LV2_State_Interface*)
- lilv_instance_get_extension_data(jalv->instance, LV2_STATE_INTERFACE_URI);
+ lilv_state_save(jalv->world, &jalv->unmap, state, NULL, path, NULL);
- if (state_iface) {
- RetrieveData data = { &jalv->map, state->props, state->num_props };
- state_iface->restore(lilv_instance_get_handle(jalv->instance),
- retrieve_callback,
- &data, 0, NULL);
- }
-#endif // HAVE_LV2_STATE
+ lilv_state_free(state);
}
int
@@ -451,244 +95,70 @@ jalv_load_presets(Jalv* jalv, PresetSink sink, void* data)
return 0;
}
-static inline const LilvNode*
-get_value(LilvWorld* world, const LilvNode* subject, const LilvNode* predicate)
+static void
+set_port_value(const char* port_symbol,
+ const LilvNode* value,
+ void* user_data)
{
- LilvNodes* vs = lilv_world_find_nodes(world, subject, predicate, NULL);
- return vs ? lilv_nodes_get_first(vs) : NULL;
-}
-
-int
-jalv_apply_preset(Jalv* jalv, const LilvNode* preset)
-{
- LilvNode* lv2_port = lilv_new_uri(jalv->world, NS_LV2 "port");
- LilvNode* lv2_symbol = lilv_new_uri(jalv->world, NS_LV2 "symbol");
- LilvNode* pset_value = lilv_new_uri(jalv->world, NS_PSET "value");
-
- LilvNodes* ports = lilv_world_find_nodes(
- jalv->world, preset, lv2_port, NULL);
- LILV_FOREACH(nodes, i, ports) {
- const LilvNode* port = lilv_nodes_get(ports, i);
- const LilvNode* symbol = get_value(jalv->world, port, lv2_symbol);
- const LilvNode* value = get_value(jalv->world, port, pset_value);
- if (!symbol) {
- fprintf(stderr, "error: Preset port missing symbol.\n");
- } else if (!value) {
- fprintf(stderr, "error: Preset port missing value.\n");
- } else if (!lilv_node_is_float(value) && !lilv_node_is_int(value)) {
- fprintf(stderr, "error: Preset port value is not a number.\n");
- } else {
- const char* sym = lilv_node_as_string(symbol);
- struct Port* p = jalv_port_by_symbol(jalv, sym);
- if (p) {
- const float fvalue = lilv_node_as_float(value);
- // Send value to plugin
- jalv_ui_write(jalv, p->index, sizeof(float), 0, &fvalue);
+ Jalv* jalv = (Jalv*)user_data;
+ struct Port* port = jalv_port_by_symbol(jalv, port_symbol);
+ if (!port) {
+ fprintf(stderr, "error: Preset port `%s' is missing\n", port_symbol);
+ return;
+ }
- // Update UI
- char buf[sizeof(ControlChange) + sizeof(float)];
- ControlChange* ev = (ControlChange*)buf;
- ev->index = p->index;
- ev->protocol = 0;
- ev->size = sizeof(float);
- *(float*)ev->body = fvalue;
- jack_ringbuffer_write(jalv->plugin_events, buf, sizeof(buf));
- } else {
- fprintf(stderr, "error: Preset port `%s' is missing\n", sym);
- }
- }
+ if (!lilv_node_is_float(value) && !lilv_node_is_int(value)) {
+ fprintf(stderr, "error: Preset port `%s' value is not a number\n",
+ port_symbol);
+ return;
}
- lilv_nodes_free(ports);
- lilv_node_free(pset_value);
- lilv_node_free(lv2_symbol);
- lilv_node_free(lv2_port);
+ const float fvalue = lilv_node_as_float(value);
- return 0;
-}
-
-static char*
-pathify(const char* in, const char* ext)
-{
- const size_t in_len = strlen(in);
- const size_t ext_len = ext ? strlen(ext) : 0;
+ // Send value to plugin
+ jalv_ui_write(jalv, port->index, sizeof(float), 0, &fvalue);
- char* out = calloc(in_len + ext_len + 1, 1);
- for (size_t i = 0; i < in_len; ++i) {
- char c = in[i];
- if (!((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9'))) {
- c = '-';
- }
- out[i] = c;
- }
- if (ext) {
- memcpy(out + in_len, ext, ext_len);
- }
- return out;
+ // Update UI
+ char buf[sizeof(ControlChange) + sizeof(float)];
+ ControlChange* ev = (ControlChange*)buf;
+ ev->index = port->index;
+ ev->protocol = 0;
+ ev->size = sizeof(float);
+ *(float*)ev->body = fvalue;
+ jack_ringbuffer_write(jalv->plugin_events, buf, sizeof(buf));
}
void
-jalv_save_port_values(Jalv* jalv,
- SerdWriter* writer,
- const SerdNode* subject)
+jalv_apply_state(Jalv* jalv, LilvState* state)
{
- for (uint32_t i = 0; i < jalv->num_ports; ++i) {
- struct Port* const port = &jalv->ports[i];
- if (port->type != TYPE_CONTROL || port->flow != FLOW_INPUT) {
- continue;
- }
-
- const LilvNode* sym = lilv_port_get_symbol(jalv->plugin, port->lilv_port);
- LilvNode* val = lilv_new_float(jalv->world, port->control);
-
- const SerdNode port_node = serd_node_from_string(
- SERD_BLANK, USTR(lilv_node_as_string(sym)));
-
- // <> lv2:port _:symbol
- SerdNode p = serd_node_from_string(SERD_URI,
- USTR(NS_LV2 "port"));
- serd_writer_write_statement(writer, SERD_ANON_O_BEGIN,
- NULL, subject, &p, &port_node, NULL, NULL);
-
- // _:symbol lv2:symbol "symbol"
- p = serd_node_from_string(SERD_URI, USTR(NS_LV2 "symbol"));
- SerdNode o = serd_node_from_string(SERD_LITERAL,
- USTR(lilv_node_as_string(sym)));
- serd_writer_write_statement(writer, SERD_ANON_CONT,
- NULL, &port_node, &p, &o, NULL, NULL);
-
- // _:symbol pset:value value
- p = serd_node_from_string(SERD_URI, USTR(NS_PSET "value"));
- o = serd_node_from_string(SERD_LITERAL,
- USTR(lilv_node_as_string(val)));
- SerdNode t = serd_node_from_string(SERD_URI, USTR(NS_XSD "decimal"));
- serd_writer_write_statement(writer, SERD_ANON_CONT,
- NULL, &port_node, &p, &o, &t, NULL);
-
- lilv_node_free(val);
- serd_writer_end_anon(writer, &port_node);
+ if (state) {
+ lilv_state_restore(
+ state, jalv->instance, set_port_value, jalv, 0, NULL);
}
}
-static int
-add_preset_to_manifest(const LilvPlugin* plugin,
- const char* manifest_path,
- const char* preset_uri,
- const char* preset_file);
-
int
-jalv_save_preset(Jalv* jalv, const char* label)
+jalv_apply_preset(Jalv* jalv, const LilvNode* preset)
{
- const char* const home = getenv("HOME");
- if (!home) {
- fprintf(stderr, "error: $HOME is undefined\n");
- return 1;
- }
-
- const char* const bundle_name = "presets.lv2/";
-
- // Create ~/.lv2/ and ~/.lv2/presets.lv2/ if necessary
- char* const lv2dir = strjoin(home, "/.lv2/");
- char* const bundle = strjoin(lv2dir, bundle_name);
- char* const filename = pathify(label, ".ttl");
- char* const path = strjoin(bundle, filename);
- char* const uri = strjoin("file://", path);
- char* const manifest_path = strjoin(bundle, "manifest.ttl");
-
- int ret = 0;
- if ((mkdir(lv2dir, 0755) && errno != EEXIST)
- || (mkdir(bundle, 0755) && errno != EEXIST)) {
- fprintf(stderr, "error: Unable to create %s (%s)\n",
- lv2dir, strerror(errno));
- ret = 2;
- goto done;
- }
-
- // Write preset file
- write_preset(jalv, path, label);
-
- // Add entry to manifest
- add_preset_to_manifest(jalv->plugin, manifest_path, filename, filename);
-
-done:
- free(manifest_path);
- free(uri);
- free(path);
- free(filename);
- free(bundle);
- free(lv2dir);
-
- return ret;
+ LilvState* state = lilv_state_new_from_world(
+ jalv->world, &jalv->map, preset);
+ jalv_apply_state(jalv, state);
+ lilv_state_free(state);
+ return 0;
}
-static int
-add_preset_to_manifest(const LilvPlugin* plugin,
- const char* manifest_path,
- const char* preset_uri,
- const char* preset_file)
+int
+jalv_save_preset(Jalv* jalv, const char* label)
{
- FILE* fd = fopen((char*)manifest_path, "a");
- if (!fd) {
- fprintf(stderr, "error: Failed to open %s (%s)\n",
- manifest_path, strerror(errno));
- return 4;
- }
-
- SerdEnv* env = serd_env_new(NULL);
- serd_env_set_prefix_from_strings(env, USTR("lv2"), USTR(NS_LV2));
- serd_env_set_prefix_from_strings(env, USTR("pset"), USTR(NS_PSET));
- serd_env_set_prefix_from_strings(env, USTR("rdfs"), USTR(NS_RDFS));
-
-#ifdef HAVE_LOCKF
- lockf(fileno(fd), F_LOCK, 0);
-#endif
-
- char* const manifest_uri = strjoin("file://", manifest_path);
-
- SerdURI base_uri;
- SerdNode base = serd_node_new_uri_from_string(
- (const uint8_t*)manifest_uri, NULL, &base_uri);
-
- SerdWriter* writer = serd_writer_new(
- SERD_TURTLE, SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED,
- env, &base_uri,
- file_sink,
- fd);
-
- fseek(fd, 0, SEEK_END);
- if (ftell(fd) == 0) {
- serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, writer);
- }
+ LilvState* const state = lilv_state_new_from_instance(
+ jalv->plugin, jalv->instance,
+ get_port_value, jalv,
+ LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE, NULL);
- SerdNode s = serd_node_from_string(SERD_URI, USTR(preset_uri));
+ lilv_state_set_label(state, label);
+ int ret = lilv_state_save(jalv->world, &jalv->unmap, state,
+ NULL, NULL, NULL);
+ lilv_state_free(state);
- // <preset> a pset:Preset
- SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "type"));
- SerdNode o = serd_node_from_string(SERD_CURIE, USTR("pset:Preset"));
- serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL);
-
- // <preset> rdfs:seeAlso <preset>
- p = serd_node_from_string(SERD_URI, USTR(NS_RDFS "seeAlso"));
- serd_writer_write_statement(writer, 0, NULL, &s, &p, &s, NULL, NULL);
-
- // <preset> lv2:appliesTo <plugin>
- p = serd_node_from_string(SERD_URI, USTR(NS_LV2 "appliesTo"));
- o = serd_node_from_string(
- SERD_URI, USTR(lilv_node_as_string(lilv_plugin_get_uri(plugin))));
- serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL);
-
- serd_writer_free(writer);
- serd_node_free(&base);
-
-#ifdef HAVE_LOCKF
- lockf(fileno(fd), F_ULOCK, 0);
-#endif
-
- fclose(fd);
- free(manifest_uri);
- serd_env_free(env);
-
- return 0;
+ return ret;
}