From 1bdb879eebbacf0af12a6d10e07756a1d5ae9082 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 18 Dec 2011 04:24:05 +0000 Subject: persist.c => state.c. git-svn-id: http://svn.drobilla.net/lad/trunk/jalv@3885 a436a847-0d15-0410-975c-d299462d15a1 --- src/persist.c | 299 ---------------------------------------------------------- src/state.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 299 insertions(+), 299 deletions(-) delete mode 100644 src/persist.c create mode 100644 src/state.c (limited to 'src') diff --git a/src/persist.c b/src/persist.c deleted file mode 100644 index f87ed6f..0000000 --- a/src/persist.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - Copyright 2007-2011 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include -#include -#include -#include -#include - -#ifdef HAVE_LV2_STATE -# include "lv2/lv2plug.in/ns/ext/state/state.h" -#endif - -#include "jalv-config.h" -#include "jalv_internal.h" - -#define NS_ATOM (const uint8_t*)"http://lv2plug.in/ns/ext/atom#" -#define NS_JALV (const uint8_t*)"http://drobilla.net/ns/jalv#" -#define NS_LV2 (const uint8_t*)"http://lv2plug.in/ns/lv2core#" -#define NS_PSET (const uint8_t*)"http://lv2plug.in/ns/ext/presets#" -#define NS_STATE (const uint8_t*)"http://lv2plug.in/ns/ext/state#" -#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" -#define NS_RDFS (const uint8_t*)"http://www.w3.org/2000/01/rdf-schema#" - -#define USTR(s) ((const uint8_t*)s) - -static int -property_cmp(const void* a, const void* b) -{ - const struct Property* pa = (const struct Property*)a; - const struct Property* pb = (const struct Property*)b; - return pa->key - pb->key; -} - -#ifdef HAVE_LV2_STATE -static int -store_callback(void* host_data, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags) -{ - Jalv* jalv = (Jalv*)host_data; - const char* key_uri = symap_unmap(jalv->symap, key); - const char* type_uri = symap_unmap(jalv->symap, 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(jalv->writer, SERD_ANON_CONT, NULL, - &jalv->state_node, &p, &o, &t, NULL); - - return 0; - } - - fprintf(stderr, "error: Failed to store property (key %d)\n", key); - return 1; -} - -static const void* -retrieve_callback(void* host_data, - uint32_t key, - size_t* size, - uint32_t* type, - uint32_t* flags) -{ - Jalv* jalv = (Jalv*)host_data; - struct Property search_key = { key, SERD_NODE_NULL, SERD_NODE_NULL }; - struct Property* prop = (struct Property*)bsearch( - &search_key, jalv->props, jalv->num_props, - sizeof(struct Property), property_cmp); - - if (prop) { - *size = prop->value.n_bytes; - *type = symap_map(jalv->symap, (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); -} - -void -jalv_save(Jalv* jalv, const char* dir) -{ - assert(!jalv->writer); - - // Set numeric locale to C so snprintf %f is Turtle compatible - char* locale = jalv_strdup(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "C"); - - const size_t dir_len = strlen(dir); - const char* const filename = "state.ttl"; - const size_t path_len = dir_len + strlen(filename); - char* const path = (char*)malloc(path_len + 1); - - snprintf(path, path_len + 1, "%s%s", dir, filename); - FILE* out_fd = fopen(path, "w"); - - 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 jalv_plugin = serd_node_from_string(SERD_URI, NS_JALV "plugin"); - - 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("")); - - jalv->writer = serd_writer_new( - SERD_TURTLE, - SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED, - env, - &SERD_URI_NULL, - file_sink, - out_fd); - - serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, jalv->writer); - - // <> jalv:plugin - serd_writer_write_statement(jalv->writer, 0, NULL, - &subject, - &jalv_plugin, - &plugin_uri, NULL, NULL); - - jalv_save_port_values(jalv, 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, (NS_STATE "instanceState")); - - // [] state:instanceState [ - jalv->state_node = serd_node_from_string(SERD_BLANK, USTR("state")); - serd_writer_write_statement(jalv->writer, SERD_ANON_O_BEGIN, NULL, - &subject, - &state_instanceState, - &jalv->state_node, NULL, NULL); - - // Write properties to state blank node - state->save(lilv_instance_get_handle(jalv->instance), - store_callback, - jalv, - LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE, - NULL); - - // ] - serd_writer_end_anon(jalv->writer, &jalv->state_node); - jalv->state_node = SERD_NODE_NULL; - } -#endif // HAVE_LV2_STATE - - // Close state file and clean up Serd - serd_writer_free(jalv->writer); - jalv->writer = NULL; - fclose(out_fd); - serd_env_free(env); - - // Reset numeric locale to original value - setlocale(LC_NUMERIC, locale); - free(locale); - - free(path); -} - -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) -{ - Jalv* jalv = (Jalv*)handle; - if (jalv->in_state) { - jalv->props = (struct Property*)realloc( - jalv->props, - sizeof(struct Property) * (++jalv->num_props)); - struct Property* prop = &jalv->props[jalv->num_props - 1]; - prop->key = symap_map(jalv->symap, (const char*)predicate->buf); - prop->value = serd_node_copy(object); - prop->datatype = serd_node_copy(object_datatype); - } else if (!strcmp((const char*)predicate->buf, "jalv:plugin")) { - const LilvPlugins* plugins = lilv_world_get_all_plugins(jalv->world); - LilvNode* plugin_uri = lilv_new_uri(jalv->world, - (const char*)object->buf); - jalv->plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); - lilv_node_free(plugin_uri); - - jalv->num_ports = lilv_plugin_get_num_ports(jalv->plugin); - jalv->ports = calloc((size_t)jalv->num_ports, sizeof(struct Port)); - - jalv_create_ports(jalv); - } else if (!strcmp((const char*)predicate->buf, "lv2:symbol")) { - serd_node_free(&jalv->last_sym); - jalv->last_sym = serd_node_copy(object); - } else if (!strcmp((const char*)predicate->buf, "pset:value")) { - const char* sym = (const char*)jalv->last_sym.buf; - struct Port* port = jalv_port_by_symbol(jalv, sym); - if (port) { - port->control = atof((const char*)object->buf); // FIXME: Check type - } else { - fprintf(stderr, "error: Failed to find port `%s'\n", sym); - } - } else if (!strcmp((const char*)predicate->buf, "state:instanceState")) { - jalv->in_state = true; - } - - return SERD_SUCCESS; -} - -void -jalv_restore(Jalv* jalv, const char* dir) -{ - jalv->reader = serd_reader_new( - SERD_TURTLE, - jalv, NULL, - NULL, - NULL, - on_statement, - NULL); - - const size_t dir_len = strlen(dir); - const size_t state_uri_len = strlen("file:///state.ttl") + dir_len + 1; - char* state_uri = (char*)malloc(state_uri_len); - snprintf(state_uri, state_uri_len, "file://%s/state.ttl", dir); - - SerdStatus st = serd_reader_read_file(jalv->reader, USTR(state_uri)); - serd_node_free(&jalv->last_sym); - if (st) { - fprintf(stderr, "Error reading state from %s (%s)\n", - state_uri, serd_strerror(st)); - return; - } - - serd_reader_free(jalv->reader); - jalv->reader = NULL; - jalv->in_state = false; - - if (jalv->props) { - qsort(jalv->props, jalv->num_props, sizeof(struct Property), property_cmp); - } -} - -void -jalv_restore_instance(Jalv* jalv, const char* dir) -{ -#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); - - if (state_iface) { - state_iface->restore(lilv_instance_get_handle(jalv->instance), - retrieve_callback, - jalv, 0, NULL); - } -#endif // HAVE_LV2_STATE -} diff --git a/src/state.c b/src/state.c new file mode 100644 index 0000000..f87ed6f --- /dev/null +++ b/src/state.c @@ -0,0 +1,299 @@ +/* + Copyright 2007-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include +#include +#include +#include + +#ifdef HAVE_LV2_STATE +# include "lv2/lv2plug.in/ns/ext/state/state.h" +#endif + +#include "jalv-config.h" +#include "jalv_internal.h" + +#define NS_ATOM (const uint8_t*)"http://lv2plug.in/ns/ext/atom#" +#define NS_JALV (const uint8_t*)"http://drobilla.net/ns/jalv#" +#define NS_LV2 (const uint8_t*)"http://lv2plug.in/ns/lv2core#" +#define NS_PSET (const uint8_t*)"http://lv2plug.in/ns/ext/presets#" +#define NS_STATE (const uint8_t*)"http://lv2plug.in/ns/ext/state#" +#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" +#define NS_RDFS (const uint8_t*)"http://www.w3.org/2000/01/rdf-schema#" + +#define USTR(s) ((const uint8_t*)s) + +static int +property_cmp(const void* a, const void* b) +{ + const struct Property* pa = (const struct Property*)a; + const struct Property* pb = (const struct Property*)b; + return pa->key - pb->key; +} + +#ifdef HAVE_LV2_STATE +static int +store_callback(void* host_data, + uint32_t key, + const void* value, + size_t size, + uint32_t type, + uint32_t flags) +{ + Jalv* jalv = (Jalv*)host_data; + const char* key_uri = symap_unmap(jalv->symap, key); + const char* type_uri = symap_unmap(jalv->symap, 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(jalv->writer, SERD_ANON_CONT, NULL, + &jalv->state_node, &p, &o, &t, NULL); + + return 0; + } + + fprintf(stderr, "error: Failed to store property (key %d)\n", key); + return 1; +} + +static const void* +retrieve_callback(void* host_data, + uint32_t key, + size_t* size, + uint32_t* type, + uint32_t* flags) +{ + Jalv* jalv = (Jalv*)host_data; + struct Property search_key = { key, SERD_NODE_NULL, SERD_NODE_NULL }; + struct Property* prop = (struct Property*)bsearch( + &search_key, jalv->props, jalv->num_props, + sizeof(struct Property), property_cmp); + + if (prop) { + *size = prop->value.n_bytes; + *type = symap_map(jalv->symap, (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); +} + +void +jalv_save(Jalv* jalv, const char* dir) +{ + assert(!jalv->writer); + + // Set numeric locale to C so snprintf %f is Turtle compatible + char* locale = jalv_strdup(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "C"); + + const size_t dir_len = strlen(dir); + const char* const filename = "state.ttl"; + const size_t path_len = dir_len + strlen(filename); + char* const path = (char*)malloc(path_len + 1); + + snprintf(path, path_len + 1, "%s%s", dir, filename); + FILE* out_fd = fopen(path, "w"); + + 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 jalv_plugin = serd_node_from_string(SERD_URI, NS_JALV "plugin"); + + 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("")); + + jalv->writer = serd_writer_new( + SERD_TURTLE, + SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED, + env, + &SERD_URI_NULL, + file_sink, + out_fd); + + serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, jalv->writer); + + // <> jalv:plugin + serd_writer_write_statement(jalv->writer, 0, NULL, + &subject, + &jalv_plugin, + &plugin_uri, NULL, NULL); + + jalv_save_port_values(jalv, 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, (NS_STATE "instanceState")); + + // [] state:instanceState [ + jalv->state_node = serd_node_from_string(SERD_BLANK, USTR("state")); + serd_writer_write_statement(jalv->writer, SERD_ANON_O_BEGIN, NULL, + &subject, + &state_instanceState, + &jalv->state_node, NULL, NULL); + + // Write properties to state blank node + state->save(lilv_instance_get_handle(jalv->instance), + store_callback, + jalv, + LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE, + NULL); + + // ] + serd_writer_end_anon(jalv->writer, &jalv->state_node); + jalv->state_node = SERD_NODE_NULL; + } +#endif // HAVE_LV2_STATE + + // Close state file and clean up Serd + serd_writer_free(jalv->writer); + jalv->writer = NULL; + fclose(out_fd); + serd_env_free(env); + + // Reset numeric locale to original value + setlocale(LC_NUMERIC, locale); + free(locale); + + free(path); +} + +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) +{ + Jalv* jalv = (Jalv*)handle; + if (jalv->in_state) { + jalv->props = (struct Property*)realloc( + jalv->props, + sizeof(struct Property) * (++jalv->num_props)); + struct Property* prop = &jalv->props[jalv->num_props - 1]; + prop->key = symap_map(jalv->symap, (const char*)predicate->buf); + prop->value = serd_node_copy(object); + prop->datatype = serd_node_copy(object_datatype); + } else if (!strcmp((const char*)predicate->buf, "jalv:plugin")) { + const LilvPlugins* plugins = lilv_world_get_all_plugins(jalv->world); + LilvNode* plugin_uri = lilv_new_uri(jalv->world, + (const char*)object->buf); + jalv->plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); + lilv_node_free(plugin_uri); + + jalv->num_ports = lilv_plugin_get_num_ports(jalv->plugin); + jalv->ports = calloc((size_t)jalv->num_ports, sizeof(struct Port)); + + jalv_create_ports(jalv); + } else if (!strcmp((const char*)predicate->buf, "lv2:symbol")) { + serd_node_free(&jalv->last_sym); + jalv->last_sym = serd_node_copy(object); + } else if (!strcmp((const char*)predicate->buf, "pset:value")) { + const char* sym = (const char*)jalv->last_sym.buf; + struct Port* port = jalv_port_by_symbol(jalv, sym); + if (port) { + port->control = atof((const char*)object->buf); // FIXME: Check type + } else { + fprintf(stderr, "error: Failed to find port `%s'\n", sym); + } + } else if (!strcmp((const char*)predicate->buf, "state:instanceState")) { + jalv->in_state = true; + } + + return SERD_SUCCESS; +} + +void +jalv_restore(Jalv* jalv, const char* dir) +{ + jalv->reader = serd_reader_new( + SERD_TURTLE, + jalv, NULL, + NULL, + NULL, + on_statement, + NULL); + + const size_t dir_len = strlen(dir); + const size_t state_uri_len = strlen("file:///state.ttl") + dir_len + 1; + char* state_uri = (char*)malloc(state_uri_len); + snprintf(state_uri, state_uri_len, "file://%s/state.ttl", dir); + + SerdStatus st = serd_reader_read_file(jalv->reader, USTR(state_uri)); + serd_node_free(&jalv->last_sym); + if (st) { + fprintf(stderr, "Error reading state from %s (%s)\n", + state_uri, serd_strerror(st)); + return; + } + + serd_reader_free(jalv->reader); + jalv->reader = NULL; + jalv->in_state = false; + + if (jalv->props) { + qsort(jalv->props, jalv->num_props, sizeof(struct Property), property_cmp); + } +} + +void +jalv_restore_instance(Jalv* jalv, const char* dir) +{ +#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); + + if (state_iface) { + state_iface->restore(lilv_instance_get_handle(jalv->instance), + retrieve_callback, + jalv, 0, NULL); + } +#endif // HAVE_LV2_STATE +} -- cgit v1.2.1