From 06b9ff8c265d7199ad5aebf1c8c7abc90cba934a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 21 Dec 2011 02:14:27 +0000 Subject: Add first-class PluginState object and make state interface more generic. git-svn-id: http://svn.drobilla.net/lad/trunk/jalv@3893 a436a847-0d15-0410-975c-d299462d15a1 --- src/jalv.c | 42 ++++++++------- src/jalv_internal.h | 17 +++--- src/state.c | 147 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 117 insertions(+), 89 deletions(-) diff --git a/src/jalv.c b/src/jalv.c index fb9ce14..452094b 100644 --- a/src/jalv.c +++ b/src/jalv.c @@ -562,27 +562,32 @@ main(int argc, char** argv) host.optional = lilv_new_uri(world, LILV_NS_LV2 "connectionOptional"); + /* Get plugin URI from loaded state or command line */ + PluginState* state = NULL; + LilvNode* plugin_uri = NULL; if (host.opts.load) { - jalv_restore(&host, host.opts.load); - } else if (argc > 1) { - const char* const plugin_uri_str = argv[1]; - - /* Get the plugin */ - LilvNode* plugin_uri = lilv_new_uri(world, plugin_uri_str); - host.plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); - lilv_node_free(plugin_uri); - if (!host.plugin) { - fprintf(stderr, "Failed to find plugin %s\n", plugin_uri_str); - lilv_world_free(world); + state = jalv_load_state(&host, host.opts.load); + 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)); + } else if (argc > 1) { + plugin_uri = lilv_new_uri(world, argv[1]); } else { fprintf(stderr, "Missing plugin URI parameter\n"); return EXIT_FAILURE; } - printf("Plugin: %s\n", - lilv_node_as_string(lilv_plugin_get_uri(host.plugin))); + /* Find plugin */ + printf("Plugin: %s\n", lilv_node_as_string(plugin_uri)); + host.plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); + lilv_node_free(plugin_uri); + if (!host.plugin) { + fprintf(stderr, "Failed to find plugin\n"); + lilv_world_free(world); + return EXIT_FAILURE; + } /* Get a plugin UI */ LilvNode* native_ui_type = jalv_native_ui_type(&host); @@ -660,11 +665,12 @@ main(int argc, char** argv) jalv_allocate_port_buffers(&host); } - /* Apply restored state to plugin instance (if applicable) */ - if (host.opts.load) { - jalv_restore_instance(&host, host.opts.load); - } else { - jalv_create_ports(&host); + /* Create port structures (host.ports) */ + jalv_create_ports(&host); + + /* Apply loaded state to plugin instance if necessary */ + if (state) { + jalv_apply_state(&host, state); } /* Set instance for instance-access extension */ diff --git a/src/jalv_internal.h b/src/jalv_internal.h index e6630e4..c35cce4 100644 --- a/src/jalv_internal.h +++ b/src/jalv_internal.h @@ -63,12 +63,11 @@ struct Port { bool old_api; /**< True for event, false for atom */ }; -struct Property { - uint32_t key; - SerdNode value; - SerdNode datatype; -}; +typedef struct PluginStateImpl PluginState; +const LilvNode* +plugin_state_get_plugin_uri(const PluginState* state); + /** Control change event, sent through ring buffers for UI updates. */ @@ -90,7 +89,6 @@ typedef struct { LilvWorld* world; /**< Lilv World */ int ui_width; /**< Requested UI width */ int ui_height; /**< Requested UI height */ - struct Property* props; /**< Restored state properties */ LV2_URID_Map map; LV2_URID_Unmap unmap; Symap* symap; /**< Symbol (URI) map */ @@ -106,7 +104,6 @@ typedef struct { struct Port* ports; /**< Port array of size num_ports */ size_t midi_buf_size; /**< Size of MIDI port buffers */ uint32_t num_ports; /**< Size of the two following arrays: */ - uint32_t num_props; /**< Number of properties */ uint32_t longest_sym; /**< Longest port symbol */ jack_nframes_t sample_rate; /**< Sample rate */ jack_nframes_t event_delta_t; /**< Frames since last update sent to UI */ @@ -176,11 +173,11 @@ jalv_save_port_values(Jalv* jalv, SerdWriter* writer, const SerdNode* subject); -void -jalv_restore(Jalv* jalv, const char* dir); +PluginState* +jalv_load_state(Jalv* jalv, const char* dir); void -jalv_restore_instance(Jalv* jalv, const char* dir); +jalv_apply_state(Jalv* jalv, PluginState* state); static inline char* jalv_strdup(const char* str) diff --git a/src/state.c b/src/state.c index 59f8785..d28ae90 100644 --- a/src/state.c +++ b/src/state.c @@ -36,14 +36,48 @@ #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 struct Property* pa = (const struct Property*)a; - const struct Property* pb = (const struct Property*)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) +{ + const PortValue* pa = (const PortValue*)a; + const PortValue* pb = (const PortValue*)b; + return strcmp((const char*)pa->symbol.buf, (const char*)pb->symbol.buf); +} + #ifdef HAVE_LV2_STATE typedef struct { LV2_URID_Unmap* unmap; @@ -83,9 +117,9 @@ store_callback(void* handle, } typedef struct { - LV2_URID_Map* map; - const struct Property* props; - const uint32_t num_props; + LV2_URID_Map* map; + const Property* props; + const uint32_t num_props; } RetrieveData; static const void* @@ -95,11 +129,11 @@ retrieve_callback(void* handle, uint32_t* type, uint32_t* flags) { - RetrieveData* data = (RetrieveData*)handle; - struct Property search_key = { key, SERD_NODE_NULL, SERD_NODE_NULL }; - struct Property* prop = (struct Property*)bsearch( + 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(struct Property), property_cmp); + sizeof(Property), property_cmp); if (prop) { *size = prop->value.n_bytes; @@ -204,20 +238,14 @@ jalv_save(Jalv* jalv, const char* dir) } typedef struct { - SerdNode symbol; - SerdNode value; - SerdNode datatype; -} PortValue; - -typedef struct { - LilvWorld* world; - LV2_URID_Map* map; - LilvNode* plugin_uri; - struct Property* props; - PortValue* ports; - uint32_t num_props; - uint32_t num_ports; - bool in_state; + 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 @@ -232,9 +260,9 @@ on_statement(void* handle, { RestoreData* data = (RestoreData*)handle; if (data->in_state) { - data->props = (struct Property*)realloc( - data->props, sizeof(struct Property) * (++data->num_props)); - struct Property* prop = &data->props[data->num_props - 1]; + 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); @@ -259,17 +287,17 @@ on_statement(void* handle, return SERD_SUCCESS; } -void -jalv_restore(Jalv* jalv, const char* dir) +PluginState* +jalv_load_state(Jalv* jalv, const char* dir) { - RestoreData* data = (RestoreData*)malloc(sizeof(RestoreData)); - memset(data, '\0', sizeof(RestoreData)); - data->world = jalv->world; - data->map = &jalv->map; + RestoreData data; + memset(&data, '\0', sizeof(RestoreData)); + data.world = jalv->world; + data.map = &jalv->map; SerdReader* reader = serd_reader_new( SERD_TURTLE, - data, NULL, + &data, NULL, NULL, NULL, on_statement, @@ -284,26 +312,36 @@ jalv_restore(Jalv* jalv, const char* dir) if (st) { fprintf(stderr, "Error reading state from %s (%s)\n", state_uri, serd_strerror(st)); - return; + free(state_uri); + return NULL; } + free(state_uri); serd_reader_free(reader); - const LilvPlugins* plugins = lilv_world_get_all_plugins(data->world); - jalv->plugin = lilv_plugins_get_by_uri(plugins, data->plugin_uri); - if (!jalv->plugin) { - fprintf(stderr, "Failed to find plugin <%s> to restore\n", - lilv_node_as_string(data->plugin_uri)); - return; + 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); } - - jalv->num_ports = lilv_plugin_get_num_ports(jalv->plugin); - jalv->ports = calloc(data->num_ports, sizeof(struct Port)); - - jalv_create_ports(jalv); - for (uint32_t i = 0; i < data->num_ports; ++i) { - PortValue* dport = &data->ports[i]; + 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) { @@ -313,25 +351,12 @@ jalv_restore(Jalv* jalv, const char* dir) } } - if (jalv->props) { - qsort(jalv->props, jalv->num_props, sizeof(struct Property), property_cmp); - } - - jalv->props = data->props; - jalv->num_props = data->num_props; - free(data->ports); - free(data); -} - -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) { - RetrieveData data = { &jalv->map, jalv->props, jalv->num_props }; + RetrieveData data = { &jalv->map, state->props, state->num_props }; state_iface->restore(lilv_instance_get_handle(jalv->instance), retrieve_callback, &data, 0, NULL); -- cgit v1.2.1