diff --git a/source/modules/lilv/lilv-0.24.0/lilv/lilv.h.orig b/source/modules/lilv/lilv-0.24.0/lilv/lilv.h.orig deleted file mode 100644 index 37dd84906..000000000 --- a/source/modules/lilv/lilv-0.24.0/lilv/lilv.h.orig +++ /dev/null @@ -1,1841 +0,0 @@ -/* - Copyright 2007-2016 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. -*/ - -/** - @file lilv.h API for Lilv, a lightweight LV2 host library. -*/ - -#ifndef LILV_LILV_H -#define LILV_LILV_H - -#include -#include -#include -#include - -#include "lv2/lv2plug.in/ns/lv2core/lv2.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" - -#ifdef LILV_SHARED -# ifdef _WIN32 -# define LILV_LIB_IMPORT __declspec(dllimport) -# define LILV_LIB_EXPORT __declspec(dllexport) -# else -# define LILV_LIB_IMPORT __attribute__((visibility("default"))) -# define LILV_LIB_EXPORT __attribute__((visibility("default"))) -# endif -# ifdef LILV_INTERNAL -# define LILV_API LILV_LIB_EXPORT -# else -# define LILV_API LILV_LIB_IMPORT -# endif -#else -# define LILV_API -#endif -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define LILV_DEPRECATED __attribute__((__deprecated__)) -#else -# define LILV_DEPRECATED -#endif - -#ifdef __cplusplus -extern "C" { -#else -# include -#endif - -#define LILV_NS_DOAP "http://usefulinc.com/ns/doap#" -#define LILV_NS_FOAF "http://xmlns.com/foaf/0.1/" -#define LILV_NS_LILV "http://drobilla.net/ns/lilv#" -#define LILV_NS_LV2 "http://lv2plug.in/ns/lv2core#" -#define LILV_NS_OWL "http://www.w3.org/2002/07/owl#" -#define LILV_NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define LILV_NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" -#define LILV_NS_XSD "http://www.w3.org/2001/XMLSchema#" - -#define LILV_URI_ATOM_PORT "http://lv2plug.in/ns/ext/atom#AtomPort" -#define LILV_URI_AUDIO_PORT "http://lv2plug.in/ns/lv2core#AudioPort" -#define LILV_URI_CONTROL_PORT "http://lv2plug.in/ns/lv2core#ControlPort" -#define LILV_URI_CV_PORT "http://lv2plug.in/ns/lv2core#CVPort" -#define LILV_URI_EVENT_PORT "http://lv2plug.in/ns/ext/event#EventPort" -#define LILV_URI_INPUT_PORT "http://lv2plug.in/ns/lv2core#InputPort" -#define LILV_URI_MIDI_EVENT "http://lv2plug.in/ns/ext/midi#MidiEvent" -#define LILV_URI_OUTPUT_PORT "http://lv2plug.in/ns/lv2core#OutputPort" -#define LILV_URI_PORT "http://lv2plug.in/ns/lv2core#Port" - -typedef struct LilvPluginImpl LilvPlugin; /**< LV2 Plugin. */ -typedef struct LilvPluginClassImpl LilvPluginClass; /**< Plugin Class. */ -typedef struct LilvPortImpl LilvPort; /**< Port. */ -typedef struct LilvScalePointImpl LilvScalePoint; /**< Scale Point. */ -typedef struct LilvUIImpl LilvUI; /**< Plugin UI. */ -typedef struct LilvNodeImpl LilvNode; /**< Typed Value. */ -typedef struct LilvWorldImpl LilvWorld; /**< Lilv World. */ -typedef struct LilvInstanceImpl LilvInstance; /**< Plugin instance. */ -typedef struct LilvStateImpl LilvState; /**< Plugin state. */ - -typedef void LilvIter; /**< Collection iterator */ -typedef void LilvPluginClasses; /**< set. */ -typedef void LilvPlugins; /**< set. */ -typedef void LilvScalePoints; /**< set. */ -typedef void LilvUIs; /**< set. */ -typedef void LilvNodes; /**< set. */ - -/** - @defgroup lilv Lilv - Lilv is a simple yet powerful C API for using LV2 plugins. - - For more information about LV2, see . - For more information about Lilv, see . - @{ -*/ - -/** - Free memory allocated by Lilv. - - This function exists because some systems require memory allocated by a - library to be freed by code in the same library. It is otherwise equivalent - to the standard C free() function. -*/ -LILV_API void -lilv_free(void* ptr); - -/** - @name Node - @{ -*/ - -/** - Convert a file URI string to a local path string. - For example, "file://foo/bar/baz.ttl" returns "/foo/bar/baz.ttl". - Return value is shared and must not be deleted by caller. - This function does not handle escaping correctly and should not be used for - general file URIs. Use lilv_file_uri_parse() instead. - @return `uri` converted to a path, or NULL on failure (URI is not local). -*/ -LILV_API LILV_DEPRECATED const char* -lilv_uri_to_path(const char* uri); - -/** - Convert a file URI string to a local path string. - For example, "file://foo/bar%20one/baz.ttl" returns "/foo/bar one/baz.ttl". - Return value must be freed by caller with lilv_free(). - @param uri The file URI to parse. - @param hostname If non-NULL, set to the hostname in the URI, if any. - @return `uri` converted to a path, or NULL on failure (URI is not local). -*/ -LILV_API char* -lilv_file_uri_parse(const char* uri, char** hostname); - -/** - Create a new URI value. - Returned value must be freed by caller with lilv_node_free(). -*/ -LILV_API LilvNode* -lilv_new_uri(LilvWorld* world, const char* uri); - -/** - Create a new file URI value. - @param world The world. - @param host Host name, or NULL. - @param path Path on host. - @return A new node that must be freed by caller. - - Relative paths are resolved against the current working directory. Note - that this may yield unexpected results if `host` is another machine. -*/ -LILV_API LilvNode* -lilv_new_file_uri(LilvWorld* world, const char* host, const char* path); - -/** - Create a new string value (with no language). - Returned value must be freed by caller with lilv_node_free(). -*/ -LILV_API LilvNode* -lilv_new_string(LilvWorld* world, const char* str); - -/** - Create a new integer value. - Returned value must be freed by caller with lilv_node_free(). -*/ -LILV_API LilvNode* -lilv_new_int(LilvWorld* world, int val); - -/** - Create a new floating point value. - Returned value must be freed by caller with lilv_node_free(). -*/ -LILV_API LilvNode* -lilv_new_float(LilvWorld* world, float val); - -/** - Create a new boolean value. - Returned value must be freed by caller with lilv_node_free(). -*/ -LILV_API LilvNode* -lilv_new_bool(LilvWorld* world, bool val); - -/** - Free a LilvNode. - It is safe to call this function on NULL. -*/ -LILV_API void -lilv_node_free(LilvNode* val); - -/** - Duplicate a LilvNode. -*/ -LILV_API LilvNode* -lilv_node_duplicate(const LilvNode* val); - -/** - Return whether two values are equivalent. -*/ -LILV_API bool -lilv_node_equals(const LilvNode* value, const LilvNode* other); - -/** - Return this value as a Turtle/SPARQL token. - Returned value must be freed by caller with lilv_free(). - - - - - - - - -
Example Turtle Tokens
URI<http://example.org/foo >
QNamedoap:name
String"this is a string"
Float1.0
Integer1
Booleantrue
-*/ -LILV_API char* -lilv_node_get_turtle_token(const LilvNode* value); - -/** - Return whether the value is a URI (resource). -*/ -LILV_API bool -lilv_node_is_uri(const LilvNode* value); - -/** - Return this value as a URI string, e.g. "http://example.org/foo". - Valid to call only if `lilv_node_is_uri(value)` returns true. - Returned value is owned by `value` and must not be freed by caller. -*/ -LILV_API const char* -lilv_node_as_uri(const LilvNode* value); - -/** - Return whether the value is a blank node (resource with no URI). -*/ -LILV_API bool -lilv_node_is_blank(const LilvNode* value); - -/** - Return this value as a blank node identifier, e.g. "genid03". - Valid to call only if `lilv_node_is_blank(value)` returns true. - Returned value is owned by `value` and must not be freed by caller. -*/ -LILV_API const char* -lilv_node_as_blank(const LilvNode* value); - -/** - Return whether this value is a literal (i.e. not a URI). - Returns true if `value` is a string or numeric value. -*/ -LILV_API bool -lilv_node_is_literal(const LilvNode* value); - -/** - Return whether this value is a string literal. - Returns true if `value` is a string value (and not numeric). -*/ -LILV_API bool -lilv_node_is_string(const LilvNode* value); - -/** - Return `value` as a string. -*/ -LILV_API const char* -lilv_node_as_string(const LilvNode* value); - -/** - Return the path of a file URI node. - Returns NULL if `value` is not a file URI. - Returned value must be freed by caller with lilv_free(). -*/ -LILV_API char* -lilv_node_get_path(const LilvNode* value, char** hostname); - -/** - Return whether this value is a decimal literal. -*/ -LILV_API bool -lilv_node_is_float(const LilvNode* value); - -/** - Return `value` as a float. - Valid to call only if `lilv_node_is_float(value)` or - `lilv_node_is_int(value)` returns true. -*/ -LILV_API float -lilv_node_as_float(const LilvNode* value); - -/** - Return whether this value is an integer literal. -*/ -LILV_API bool -lilv_node_is_int(const LilvNode* value); - -/** - Return `value` as an integer. - Valid to call only if `lilv_node_is_int(value)` returns true. -*/ -LILV_API int -lilv_node_as_int(const LilvNode* value); - -/** - Return whether this value is a boolean. -*/ -LILV_API bool -lilv_node_is_bool(const LilvNode* value); - -/** - Return `value` as a bool. - Valid to call only if `lilv_node_is_bool(value)` returns true. -*/ -LILV_API bool -lilv_node_as_bool(const LilvNode* value); - -/** - @} - @name Collections - Lilv has several collection types for holding various types of value: -
    -
  • LilvPlugins (function prefix "lilv_plugins_")
  • -
  • LilvPluginClasses (function prefix "lilv_plugin_classes_")
  • -
  • LilvScalePoints (function prefix "lilv_scale_points_")
  • -
  • LilvNodes (function prefix "lilv_nodes_")
  • -
  • LilvUIs (function prefix "lilv_uis_")
  • -
- - Each collection type supports a similar basic API (except LilvPlugins which - is internal and thus lacks a free function): -
    -
  • void PREFIX_free (coll)
  • -
  • unsigned PREFIX_size (coll)
  • -
  • LilvIter* PREFIX_begin (coll)
  • -
- @{ -*/ - -/* Collections */ - -/** - Iterate over each element of a collection. - @code - LILV_FOREACH(plugin_classes, i, classes) { - LilvPluginClass c = lilv_plugin_classes_get(classes, i); - // ... - } - @endcode -*/ -#define LILV_FOREACH(colltype, iter, collection) \ - for (LilvIter* (iter) = lilv_ ## colltype ## _begin(collection); \ - !lilv_ ## colltype ## _is_end(collection, iter); \ - (iter) = lilv_ ## colltype ## _next(collection, iter)) - -/* LilvPluginClasses */ - -LILV_API void -lilv_plugin_classes_free(LilvPluginClasses* collection); - -LILV_API unsigned -lilv_plugin_classes_size(const LilvPluginClasses* collection); - -LILV_API LilvIter* -lilv_plugin_classes_begin(const LilvPluginClasses* collection); - -LILV_API const LilvPluginClass* -lilv_plugin_classes_get(const LilvPluginClasses* collection, LilvIter* i); - -LILV_API LilvIter* -lilv_plugin_classes_next(const LilvPluginClasses* collection, LilvIter* i); - -LILV_API bool -lilv_plugin_classes_is_end(const LilvPluginClasses* collection, LilvIter* i); - -/** - Get a plugin class from `classes` by URI. - Return value is shared (stored in `classes`) and must not be freed or - modified by the caller in any way. - @return NULL if no plugin class with `uri` is found in `classes`. -*/ -LILV_API const LilvPluginClass* -lilv_plugin_classes_get_by_uri(const LilvPluginClasses* classes, - const LilvNode* uri); - -/* ScalePoints */ - -LILV_API void -lilv_scale_points_free(LilvScalePoints* collection); - -LILV_API unsigned -lilv_scale_points_size(const LilvScalePoints* collection); - -LILV_API LilvIter* -lilv_scale_points_begin(const LilvScalePoints* collection); - -LILV_API const LilvScalePoint* -lilv_scale_points_get(const LilvScalePoints* collection, LilvIter* i); - -LILV_API LilvIter* -lilv_scale_points_next(const LilvScalePoints* collection, LilvIter* i); - -LILV_API bool -lilv_scale_points_is_end(const LilvScalePoints* collection, LilvIter* i); - -/* UIs */ - -LILV_API void -lilv_uis_free(LilvUIs* collection); - -LILV_API unsigned -lilv_uis_size(const LilvUIs* collection); - -LILV_API LilvIter* -lilv_uis_begin(const LilvUIs* collection); - -LILV_API const LilvUI* -lilv_uis_get(const LilvUIs* collection, LilvIter* i); - -LILV_API LilvIter* -lilv_uis_next(const LilvUIs* collection, LilvIter* i); - -LILV_API bool -lilv_uis_is_end(const LilvUIs* collection, LilvIter* i); - -/** - Get a UI from `uis` by URI. - Return value is shared (stored in `uis`) and must not be freed or - modified by the caller in any way. - @return NULL if no UI with `uri` is found in `list`. -*/ -LILV_API const LilvUI* -lilv_uis_get_by_uri(const LilvUIs* uis, - const LilvNode* uri); - -/* Nodes */ - -LILV_API void -lilv_nodes_free(LilvNodes* collection); - -LILV_API unsigned -lilv_nodes_size(const LilvNodes* collection); - -LILV_API LilvIter* -lilv_nodes_begin(const LilvNodes* collection); - -LILV_API const LilvNode* -lilv_nodes_get(const LilvNodes* collection, LilvIter* i); - -LILV_API LilvIter* -lilv_nodes_next(const LilvNodes* collection, LilvIter* i); - -LILV_API bool -lilv_nodes_is_end(const LilvNodes* collection, LilvIter* i); - -LILV_API LilvNode* -lilv_nodes_get_first(const LilvNodes* collection); - -/** - Return whether `values` contains `value`. -*/ -LILV_API bool -lilv_nodes_contains(const LilvNodes* values, const LilvNode* value); - -/** - Return a new LilvNodes that contains all nodes from both `a` and `b`. -*/ -LILV_API LilvNodes* -lilv_nodes_merge(const LilvNodes* a, const LilvNodes* b); - -/* Plugins */ - -LILV_API unsigned -lilv_plugins_size(const LilvPlugins* collection); - -LILV_API LilvIter* -lilv_plugins_begin(const LilvPlugins* collection); - -LILV_API const LilvPlugin* -lilv_plugins_get(const LilvPlugins* collection, LilvIter* i); - -LILV_API LilvIter* -lilv_plugins_next(const LilvPlugins* collection, LilvIter* i); - -LILV_API bool -lilv_plugins_is_end(const LilvPlugins* collection, LilvIter* i); - -/** - Get a plugin from `plugins` by URI. - Return value is shared (stored in `plugins`) and must not be freed or - modified by the caller in any way. - @return NULL if no plugin with `uri` is found in `plugins`. -*/ -LILV_API const LilvPlugin* -lilv_plugins_get_by_uri(const LilvPlugins* plugins, - const LilvNode* uri); - -/** - @} - @name World - The "world" represents all Lilv state, and is used to discover/load/cache - LV2 data (plugins, UIs, and extensions). - Normal hosts which just need to load plugins by URI should simply use - lilv_world_load_all() to discover/load the system's LV2 resources. - @{ -*/ - -/** - Initialize a new, empty world. - If initialization fails, NULL is returned. -*/ -LILV_API LilvWorld* -lilv_world_new(void); - -/** - Enable/disable language filtering. - Language filtering applies to any functions that return (a) value(s). - With filtering enabled, Lilv will automatically return the best value(s) - for the current LANG. With filtering disabled, all matching values will - be returned regardless of language tag. Filtering is enabled by default. -*/ -#define LILV_OPTION_FILTER_LANG "http://drobilla.net/ns/lilv#filter-lang" - -/** - Enable/disable dynamic manifest support. - Dynamic manifest data will only be loaded if this option is true. -*/ -#define LILV_OPTION_DYN_MANIFEST "http://drobilla.net/ns/lilv#dyn-manifest" - -/** - Set an option option for `world`. - - Currently recognized options: - @ref LILV_OPTION_FILTER_LANG - @ref LILV_OPTION_DYN_MANIFEST -*/ -LILV_API void -lilv_world_set_option(LilvWorld* world, - const char* uri, - const LilvNode* value); - -/** - Destroy the world, mwahaha. - It is safe to call this function on NULL. - Note that destroying `world` will destroy all the objects it contains - (e.g. instances of LilvPlugin). Do not destroy the world until you are - finished with all objects that came from it. -*/ -LILV_API void -lilv_world_free(LilvWorld* world); - -/** - Load all installed LV2 bundles on the system. - This is the recommended way for hosts to load LV2 data. It implements the - established/standard best practice for discovering all LV2 data on the - system. The environment variable LV2_PATH may be used to control where - this function will look for bundles. - - Hosts should use this function rather than explicitly load bundles, except - in special circumstances (e.g. development utilities, or hosts that ship - with special plugin bundles which are installed to a known location). -*/ -LILV_API void -lilv_world_load_all(LilvWorld* world); - -/** - Load a specific bundle. - `bundle_uri` must be a fully qualified URI to the bundle directory, - with the trailing slash, eg. file:///usr/lib/lv2/foo.lv2/ - - Normal hosts should not need this function (use lilv_world_load_all()). - - Hosts MUST NOT attach any long-term significance to bundle paths - (e.g. in save files), since there are no guarantees they will remain - unchanged between (or even during) program invocations. Plugins (among - other things) MUST be identified by URIs (not paths) in save files. -*/ -LILV_API void -lilv_world_load_bundle(LilvWorld* world, - const LilvNode* bundle_uri); - -/** - Load all specifications from currently loaded bundles. - - This is for hosts that explicitly load specific bundles, its use is not - necessary when using lilv_world_load_all(). This function parses the - specifications and adds them to the model. -*/ -LILV_API void -lilv_world_load_specifications(LilvWorld* world); - -/** - Load all plugin classes from currently loaded specifications. - - Must be called after lilv_world_load_specifications(). This is for hosts - that explicitly load specific bundles, its use is not necessary when using - lilv_world_load_all(). -*/ -LILV_API void -lilv_world_load_plugin_classes(LilvWorld* world); - -/** - Unload a specific bundle. - - This unloads statements loaded by lilv_world_load_bundle(). Note that this - is not necessarily all information loaded from the bundle. If any resources - have been separately loaded with lilv_world_load_resource(), they must be - separately unloaded with lilv_world_unload_resource(). -*/ -LILV_API int -lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri); - -/** - Load all the data associated with the given `resource`. - @param world The world. - @param resource Must be a subject (i.e. a URI or a blank node). - @return The number of files parsed, or -1 on error - - All accessible data files linked to `resource` with rdfs:seeAlso will be - loaded into the world model. -*/ -LILV_API int -lilv_world_load_resource(LilvWorld* world, - const LilvNode* resource); - -/** - Unload all the data associated with the given `resource`. - @param world The world. - @param resource Must be a subject (i.e. a URI or a blank node). - - This unloads all data loaded by a previous call to - lilv_world_load_resource() with the given `resource`. -*/ -LILV_API int -lilv_world_unload_resource(LilvWorld* world, - const LilvNode* resource); - -/** - Get the parent of all other plugin classes, lv2:Plugin. -*/ -LILV_API const LilvPluginClass* -lilv_world_get_plugin_class(const LilvWorld* world); - -/** - Return a list of all found plugin classes. - Returned list is owned by world and must not be freed by the caller. -*/ -LILV_API const LilvPluginClasses* -lilv_world_get_plugin_classes(const LilvWorld* world); - -/** - Return a list of all found plugins. - The returned list contains just enough references to query - or instantiate plugins. The data for a particular plugin will not be - loaded into memory until a call to an lilv_plugin_* function results in - a query (at which time the data is cached with the LilvPlugin so future - queries are very fast). - - The returned list and the plugins it contains are owned by `world` - and must not be freed by caller. -*/ -LILV_API const LilvPlugins* -lilv_world_get_all_plugins(const LilvWorld* world); - -/** - Find nodes matching a triple pattern. - Either `subject` or `object` may be NULL (i.e. a wildcard), but not both. - @return All matches for the wildcard field, or NULL. -*/ -LILV_API LilvNodes* -lilv_world_find_nodes(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object); - -/** - Find a single node that matches a pattern. - Exactly one of `subject`, `predicate`, `object` must be NULL. - This function is equivalent to - lilv_nodes_get_first(lilv_world_find_nodes(...)) but simplifies the common - case of only wanting a single value. - @return the first matching node, or NULL if no matches are found. -*/ -LILV_API LilvNode* -lilv_world_get(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object); - -/** - Return true iff a statement matching a certain pattern exists. - - This is useful for checking if particular statement exists without having to - bother with collections and memory management. - - @param world The world. - @param subject Subject of statement, or NULL for anything. - @param predicate Predicate (key) of statement, or NULL for anything. - @param object Object (value) of statement, or NULL for anything. -*/ -LILV_API bool -lilv_world_ask(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object); - -/** - Get an LV2 symbol for some subject. - - This will return the lv2:symbol property of the subject if it is given - explicitly, and otherwise will attempt to derive a symbol from the URI. - @return A string node that is a valid LV2 symbol, or NULL on error. -*/ -LILV_API LilvNode* -lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject); - -/** - @} - @name Plugin - @{ -*/ - -/** - Check if `plugin` is valid. - This is not a rigorous validator, but can be used to reject some malformed - plugins that could cause bugs (e.g. plugins with missing required fields). - - Note that normal hosts do NOT need to use this - lilv does not - load invalid plugins into plugin lists. This is included for plugin - testing utilities, etc. - @return true iff `plugin` is valid. -*/ -LILV_API bool -lilv_plugin_verify(const LilvPlugin* plugin); - -/** - Get the URI of `plugin`. - Any serialization that refers to plugins should refer to them by this. - Hosts SHOULD NOT save any filesystem paths, plugin indexes, etc. in saved - files; save only the URI. - - The URI is a globally unique identifier for one specific plugin. Two - plugins with the same URI are compatible in port signature, and should - be guaranteed to work in a compatible and consistent way. If a plugin - is upgraded in an incompatible way (eg if it has different ports), it - MUST have a different URI than it's predecessor. - - @return A shared URI value which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_plugin_get_uri(const LilvPlugin* plugin); - -/** - Get the (resolvable) URI of the plugin's "main" bundle. - This returns the URI of the bundle where the plugin itself was found. Note - that the data for a plugin may be spread over many bundles, that is, - lilv_plugin_get_data_uris() may return URIs which are not within this - bundle. - - Typical hosts should not need to use this function. - Note this always returns a fully qualified URI. If you want a local - filesystem path, use lilv_file_uri_parse(). - @return a shared string which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_plugin_get_bundle_uri(const LilvPlugin* plugin); - -/** - Get the (resolvable) URIs of the RDF data files that define a plugin. - Typical hosts should not need to use this function. - Note this always returns fully qualified URIs. If you want local - filesystem paths, use lilv_file_uri_parse(). - @return a list of complete URLs eg. "file:///foo/ABundle.lv2/aplug.ttl", - which is shared and must not be modified or freed. -*/ -LILV_API const LilvNodes* -lilv_plugin_get_data_uris(const LilvPlugin* plugin); - -/** - Get the (resolvable) URI of the shared library for `plugin`. - Note this always returns a fully qualified URI. If you want a local - filesystem path, use lilv_file_uri_parse(). - @return a shared string which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_plugin_get_library_uri(const LilvPlugin* plugin); - -/** - Get the name of `plugin`. - This returns the name (doap:name) of the plugin. The name may be - translated according to the current locale, this value MUST NOT be used - as a plugin identifier (use the URI for that). - Returned value must be freed by the caller. -*/ -LILV_API LilvNode* -lilv_plugin_get_name(const LilvPlugin* plugin); - -/** - Get the class this plugin belongs to (e.g. Filters). -*/ -LILV_API const LilvPluginClass* -lilv_plugin_get_class(const LilvPlugin* plugin); - -/** - Get a value associated with the plugin in a plugin's data files. - `predicate` must be either a URI or a QName. - - Returns the ?object of all triples found of the form: - - <plugin-uri> predicate ?object - - May return NULL if the property was not found, or if object(s) is not - sensibly represented as a LilvNodes (e.g. blank nodes). - Return value must be freed by caller with lilv_nodes_free(). -*/ -LILV_API LilvNodes* -lilv_plugin_get_value(const LilvPlugin* p, - const LilvNode* predicate); - -/** - Return whether a feature is supported by a plugin. - This will return true if the feature is an optional or required feature - of the plugin. -*/ -LILV_API bool -lilv_plugin_has_feature(const LilvPlugin* p, - const LilvNode* feature_uri); - -/** - Get the LV2 Features supported (required or optionally) by a plugin. - A feature is "supported" by a plugin if it is required OR optional. - - Since required features have special rules the host must obey, this function - probably shouldn't be used by normal hosts. Using lilv_plugin_get_optional_features() - and lilv_plugin_get_required_features() separately is best in most cases. - - Returned value must be freed by caller with lilv_nodes_free(). -*/ -LILV_API LilvNodes* -lilv_plugin_get_supported_features(const LilvPlugin* p); - -/** - Get the LV2 Features required by a plugin. - If a feature is required by a plugin, hosts MUST NOT use the plugin if they do not - understand (or are unable to support) that feature. - - All values returned here MUST be passed to the plugin's instantiate method - (along with data, if necessary, as defined by the feature specification) - or plugin instantiation will fail. - - Return value must be freed by caller with lilv_nodes_free(). -*/ -LILV_API LilvNodes* -lilv_plugin_get_required_features(const LilvPlugin* p); - -/** - Get the LV2 Features optionally supported by a plugin. - Hosts MAY ignore optional plugin features for whatever reasons. Plugins - MUST operate (at least somewhat) if they are instantiated without being - passed optional features. - - Return value must be freed by caller with lilv_nodes_free(). -*/ -LILV_API LilvNodes* -lilv_plugin_get_optional_features(const LilvPlugin* p); - -/** - Return whether or not a plugin provides a specific extension data. -*/ -LILV_API bool -lilv_plugin_has_extension_data(const LilvPlugin* p, - const LilvNode* uri); - -/** - Get a sequence of all extension data provided by a plugin. - This can be used to find which URIs lilv_instance_get_extension_data() - will return a value for without instantiating the plugin. -*/ -LILV_API LilvNodes* -lilv_plugin_get_extension_data(const LilvPlugin* p); - -/** - Get the number of ports on this plugin. -*/ -LILV_API uint32_t -lilv_plugin_get_num_ports(const LilvPlugin* p); - -/** - Get the port ranges (minimum, maximum and default values) for all ports. - `min_values`, `max_values` and `def_values` must either point to an array - of N floats, where N is the value returned by lilv_plugin_get_num_ports() - for this plugin, or NULL. The elements of the array will be set to the - the minimum, maximum and default values of the ports on this plugin, - with array index corresponding to port index. If a port doesn't have a - minimum, maximum or default value, or the port's type is not float, the - corresponding array element will be set to NAN. - - This is a convenience method for the common case of getting the range of - all float ports on a plugin, and may be significantly faster than - repeated calls to lilv_port_get_range(). -*/ -LILV_API void -lilv_plugin_get_port_ranges_float(const LilvPlugin* p, - float* min_values, - float* max_values, - float* def_values); - -/** - Get the number of ports on this plugin that are members of some class(es). - Note that this is a varargs function so ports fitting any type 'profile' - desired can be found quickly. REMEMBER TO TERMINATE THE PARAMETER LIST - OF THIS FUNCTION WITH NULL OR VERY NASTY THINGS WILL HAPPEN. -*/ -LILV_API uint32_t -lilv_plugin_get_num_ports_of_class(const LilvPlugin* p, - const LilvNode* class_1, ...); - -#ifndef SWIG -/** - Variant of lilv_plugin_get_num_ports_of_class() that takes a va_list. - - This function calls va_arg() on `args` but does not call va_end(). -*/ -LILV_API uint32_t -lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p, - const LilvNode* class_1, - va_list args); -#endif - -/** - Return whether or not the plugin introduces (and reports) latency. - The index of the latency port can be found with - lilv_plugin_get_latency_port() ONLY if this function returns true. -*/ -LILV_API bool -lilv_plugin_has_latency(const LilvPlugin* p); - -/** - Return the index of the plugin's latency port. - It is a fatal error to call this on a plugin without checking if the port - exists by first calling lilv_plugin_has_latency(). - - Any plugin that introduces unwanted latency that should be compensated for - (by hosts with the ability/need) MUST provide this port, which is a control - rate output port that reports the latency for each cycle in frames. -*/ -LILV_API uint32_t -lilv_plugin_get_latency_port_index(const LilvPlugin* p); - -/** - Get a port on `plugin` by `index`. -*/ -LILV_API const LilvPort* -lilv_plugin_get_port_by_index(const LilvPlugin* plugin, - uint32_t index); - -/** - Get a port on `plugin` by `symbol`. - Note this function is slower than lilv_plugin_get_port_by_index(), - especially on plugins with a very large number of ports. -*/ -LILV_API const LilvPort* -lilv_plugin_get_port_by_symbol(const LilvPlugin* plugin, - const LilvNode* symbol); - -/** - Get a port on `plugin` by its lv2:designation. - - The designation of a port describes the meaning, assignment, allocation or - role of the port, e.g. "left channel" or "gain". If found, the port with - matching `port_class` and `designation` is be returned, otherwise NULL is - returned. The `port_class` can be used to distinguish the input and output - ports for a particular designation. If `port_class` is NULL, any port with - the given designation will be returned. -*/ -LILV_API const LilvPort* -lilv_plugin_get_port_by_designation(const LilvPlugin* plugin, - const LilvNode* port_class, - const LilvNode* designation); - -/** - Get the project the plugin is a part of. - - More information about the project can be read via lilv_world_find_nodes(), - typically using properties from DOAP (e.g. doap:name). -*/ -LILV_API LilvNode* -lilv_plugin_get_project(const LilvPlugin* plugin); - -/** - Get the full name of the plugin's author. - Returns NULL if author name is not present. - Returned value must be freed by caller. -*/ -LILV_API LilvNode* -lilv_plugin_get_author_name(const LilvPlugin* plugin); - -/** - Get the email address of the plugin's author. - Returns NULL if author email address is not present. - Returned value must be freed by caller. -*/ -LILV_API LilvNode* -lilv_plugin_get_author_email(const LilvPlugin* plugin); - -/** - Get the address of the plugin author's home page. - Returns NULL if author homepage is not present. - Returned value must be freed by caller. -*/ -LILV_API LilvNode* -lilv_plugin_get_author_homepage(const LilvPlugin* plugin); - -/** - Return true iff `plugin` has been replaced by another plugin. - - The plugin will still be usable, but hosts should hide them from their - user interfaces to prevent users from using deprecated plugins. -*/ -LILV_API bool -lilv_plugin_is_replaced(const LilvPlugin* plugin); - -/** - Write the Turtle description of `plugin` to `plugin_file`. - - This function is particularly useful for porting plugins in conjunction with - an LV2 bridge such as NASPRO. -*/ -LILV_API void -lilv_plugin_write_description(LilvWorld* world, - const LilvPlugin* plugin, - const LilvNode* base_uri, - FILE* plugin_file); - -/** - Write a manifest entry for `plugin` to `manifest_file`. - - This function is intended for use with lilv_plugin_write_description() to - write a complete description of a plugin to a bundle. -*/ -LILV_API void -lilv_plugin_write_manifest_entry(LilvWorld* world, - const LilvPlugin* plugin, - const LilvNode* base_uri, - FILE* manifest_file, - const char* plugin_file_path); - -/** - Get the resources related to `plugin` with lv2:appliesTo. - - Some plugin-related resources are not linked directly to the plugin with - rdfs:seeAlso and thus will not be automatically loaded along with the plugin - data (usually for performance reasons). All such resources of the given @c - type related to `plugin` can be accessed with this function. - - If `type` is NULL, all such resources will be returned, regardless of type. - - To actually load the data for each returned resource, use - lilv_world_load_resource(). -*/ -LILV_API LilvNodes* -lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type); - -/** - @} - @name Port - @{ -*/ - -/** - Get the RDF node of `port`. - - Ports nodes may be may be URIs or blank nodes. - - @return A shared node which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_port_get_node(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Port analog of lilv_plugin_get_value(). -*/ -LILV_API LilvNodes* -lilv_port_get_value(const LilvPlugin* plugin, - const LilvPort* port, - const LilvNode* predicate); - -/** - Get a single property value of a port. - - This is equivalent to lilv_nodes_get_first(lilv_port_get_value(...)) but is - simpler to use in the common case of only caring about one value. The - caller is responsible for freeing the returned node. -*/ -LILV_API LilvNode* -lilv_port_get(const LilvPlugin* plugin, - const LilvPort* port, - const LilvNode* predicate); - -/** - Return the LV2 port properties of a port. -*/ -LILV_API LilvNodes* -lilv_port_get_properties(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Return whether a port has a certain property. -*/ -LILV_API bool -lilv_port_has_property(const LilvPlugin* p, - const LilvPort* port, - const LilvNode* property_uri); - -/** - Return whether a port supports a certain event type. - - More precisely, this returns true iff the port has an atom:supports or an - ev:supportsEvent property with `event_type` as the value. -*/ -LILV_API bool -lilv_port_supports_event(const LilvPlugin* p, - const LilvPort* port, - const LilvNode* event_type); - -/** - Get the index of a port. - The index is only valid for the life of the plugin and may change between - versions. For a stable identifier, use the symbol. -*/ -LILV_API uint32_t -lilv_port_get_index(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Get the symbol of a port. - The 'symbol' is a short string, a valid C identifier. - Returned value is owned by `port` and must not be freed. -*/ -LILV_API const LilvNode* -lilv_port_get_symbol(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Get the name of a port. - This is guaranteed to return the untranslated name (the doap:name in the - data file without a language tag). Returned value must be freed by - the caller. -*/ -LILV_API LilvNode* -lilv_port_get_name(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Get all the classes of a port. - This can be used to determine if a port is an input, output, audio, - control, midi, etc, etc, though it's simpler to use lilv_port_is_a(). - The returned list does not include lv2:Port, which is implied. - Returned value is shared and must not be destroyed by caller. -*/ -LILV_API const LilvNodes* -lilv_port_get_classes(const LilvPlugin* plugin, - const LilvPort* port); - -/** - Determine if a port is of a given class (input, output, audio, etc). - For convenience/performance/extensibility reasons, hosts are expected to - create a LilvNode for each port class they "care about". Well-known type - URI strings are defined (e.g. LILV_URI_INPUT_PORT) for convenience, but - this function is designed so that Lilv is usable with any port types - without requiring explicit support in Lilv. -*/ -LILV_API bool -lilv_port_is_a(const LilvPlugin* plugin, - const LilvPort* port, - const LilvNode* port_class); - -/** - Get the default, minimum, and maximum values of a port. - - `def`, `min`, and `max` are outputs, pass pointers to uninitialized - LilvNode* variables. These will be set to point at new values (which must - be freed by the caller using lilv_node_free()), or NULL if the value does - not exist. -*/ -LILV_API void -lilv_port_get_range(const LilvPlugin* plugin, - const LilvPort* port, - LilvNode** deflt, - LilvNode** min, - LilvNode** max); - -/** - Get the scale points (enumeration values) of a port. - This returns a collection of 'interesting' named values of a port - (e.g. appropriate entries for a UI selector associated with this port). - Returned value may be NULL if `port` has no scale points, otherwise it - must be freed by caller with lilv_scale_points_free(). -*/ -LILV_API LilvScalePoints* -lilv_port_get_scale_points(const LilvPlugin* plugin, - const LilvPort* port); - -/** - @} - @name Plugin State - @{ -*/ - -/** - Load a state snapshot from the world RDF model. - This function can be used to load the default state of a plugin by passing - the plugin URI as the `subject` parameter. - @param world The world. - @param map URID mapper. - @param subject The subject of the state description (e.g. a preset URI). - @return A new LilvState which must be freed with lilv_state_free(), or NULL. -*/ -LILV_API LilvState* -lilv_state_new_from_world(LilvWorld* world, - LV2_URID_Map* map, - const LilvNode* subject); - -/** - Load a state snapshot from a file. - @param world The world. - @param map URID mapper. - @param subject The subject of the state description (e.g. a preset URI). - @param path The path of the file containing the state description. - @return A new LilvState which must be freed with lilv_state_free(). - - If `subject` is NULL, it is taken to be the URI of the file (i.e. - "<>" in Turtle). - - This function parses the file separately to create the state, it does not - parse the file into the world model, i.e. the returned state is the only - new memory consumed once this function returns. -*/ -LILV_API LilvState* -lilv_state_new_from_file(LilvWorld* world, - LV2_URID_Map* map, - const LilvNode* subject, - const char* path); - -/** - Load a state snapshot from a string made by lilv_state_to_string(). -*/ -LILV_API LilvState* -lilv_state_new_from_string(LilvWorld* world, - LV2_URID_Map* map, - const char* str); - -/** - Function to get a port value. - @param port_symbol The symbol of the port. - @param user_data The user_data passed to lilv_state_new_from_instance(). - @param size (Output) The size of the returned value. - @param type (Output) The URID of the type of the returned value. - @return A pointer to the port value. - - This function MUST set `size` and `type` appropriately. -*/ -typedef const void* (*LilvGetPortValueFunc)(const char* port_symbol, - void* user_data, - uint32_t* size, - uint32_t* type); - -/** - Create a new state snapshot from a plugin instance. - - @param plugin The plugin this state applies to. - - @param instance An instance of `plugin`. - - @param map The map to use for mapping URIs in state. - - @param file_dir Directory of files created by the plugin earlier (or NULL). - This is for hosts that support file creation at any time with state - state:makePath. These files will be copied as necessary to `copy_dir` and - not be referred to directly in state (a temporary directory is appropriate). - - @param copy_dir Directory of copies of files in `file_dir` (or NULL). This - directory will have the same structure as `file_dir` but with possibly - modified file names to distinguish different revisions. If you only care - about saving one state snapshot, it can be the same as `save_dir`. Plugin - state will refer to files in this directory. - - @param save_dir Directory of files created by plugin during save (or NULL). - If the state will be saved, this should be the bundle directory later passed - to lilv_state_save(). - - @param get_value Function to get port values (or NULL). If NULL, the - returned state will not represent port values. This should only be NULL in - hosts that save and restore port values via some other mechanism. - - @param user_data User data to pass to `get_value`. - - @param link_dir Directory of links to external files (or NULL). A link will - be made in this directory to any external files referred to in plugin state. - In turn, links will be created in the save directory to these links (e.g. - save_dir/file => link_dir/file => /foo/bar/file). This allows many state - snapshots to share a single link to an external file, so archival - (e.g. with tar -h) will not create several copies of the file. If this is - not required, it can be the same as save_dir. - - @param flags Bitwise OR of LV2_State_Flags values. - - @param features Features to pass LV2_State_Interface.save(). - - @return A new LilvState which must be freed with lilv_state_free(). - - This function may be called simultaneously with any instance function - (except discovery functions) unless the threading class of that function - explicitly disallows this. - - To support advanced file functionality, there are several directory - parameters. Simple hosts that only wish to save a single plugins state once - may simply use the same directory for all of them (or pass NULL to not - support files at all). The multiple parameters are necessary to support - saving an instances state many times while avoiding any duplication of data. - - If supported (via state:makePath passed to LV2_Descriptor::instantiate()), - `file_dir` should be the directory where any files created by the plugin - (not during save time, e.g. during instantiation) are stored. These files - will be copied to preserve their state at this time.plugin-created files are stored. - Lilv will assume any files within this directory (recursively) are created - by the plugin and all other files are immutable. Note that this function - does not save the state, use lilv_state_save() for that. - - See state.h from the - LV2 State extension for details on the `flags` and `features` parameters. -*/ -LILV_API LilvState* -lilv_state_new_from_instance(const LilvPlugin* plugin, - LilvInstance* instance, - LV2_URID_Map* map, - const char* file_dir, - const char* copy_dir, - const char* link_dir, - const char* save_dir, - LilvGetPortValueFunc get_value, - void* user_data, - uint32_t flags, - const LV2_Feature *const * features); - -/** - Free `state`. -*/ -LILV_API void -lilv_state_free(LilvState* state); - -/** - Return true iff `a` is equivalent to `b`. -*/ -LILV_API bool -lilv_state_equals(const LilvState* a, const LilvState* b); - -/** - Return the number of properties in `state`. -*/ -LILV_API unsigned -lilv_state_get_num_properties(const LilvState* state); - -/** - Get the URI of the plugin `state` applies to. -*/ -LILV_API const LilvNode* -lilv_state_get_plugin_uri(const LilvState* state); - -/** - Get the URI of `state`. - - This may return NULL if the state has not been saved and has no URI. -*/ -LILV_API const LilvNode* -lilv_state_get_uri(const LilvState* state); - -/** - Get the label of `state`. -*/ -LILV_API const char* -lilv_state_get_label(const LilvState* state); - -/** - Set the label of `state`. -*/ -LILV_API void -lilv_state_set_label(LilvState* state, - const char* label); - -/** - Set a metadata property on `state`. - @param state The state to set the metadata for. - @param key The key to store `value` under (URID). - @param value Pointer to the value to be stored. - @param size The size of `value` in bytes. - @param type The type of `value` (URID). - @param flags LV2_State_Flags for `value`. - @return 0 on success. - - This is a generic version of lilv_state_set_label(), which sets metadata - properties visible to hosts, but not plugins. This allows storing useful - information such as comments or preset banks. -*/ -LILV_API int -lilv_state_set_metadata(LilvState* state, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags); - -/** - Function to set a port value. - @param port_symbol The symbol of the port. - @param user_data The user_data passed to lilv_state_restore(). - @param size The size of `value`. - @param type The URID of the type of `value`. - @param value A pointer to the port value. -*/ -typedef void (*LilvSetPortValueFunc)(const char* port_symbol, - void* user_data, - const void* value, - uint32_t size, - uint32_t type); - -/** - Enumerate the port values in a state snapshot. - @param state The state to retrieve port values from. - @param set_value A function to receive port values. - @param user_data User data to pass to `set_value`. - - This function is a subset of lilv_state_restore() that only fires the - `set_value` callback and does not directly affect a plugin instance. This - is useful in hosts that need to retrieve the port values in a state snapshot - for special handling. -*/ -LILV_API void -lilv_state_emit_port_values(const LilvState* state, - LilvSetPortValueFunc set_value, - void* user_data); - -/** - Restore a plugin instance from a state snapshot. - @param state The state to restore, which must apply to the correct plugin. - @param instance An instance of the plugin `state` applies to, or NULL. - @param set_value A function to set a port value (may be NULL). - @param user_data User data to pass to `set_value`. - @param flags Bitwise OR of LV2_State_Flags values. - @param features Features to pass LV2_State_Interface.restore(). - - This will set all the properties of `instance`, if given, to the values - stored in `state`. If `set_value` is provided, it will be called (with the - given `user_data`) to restore each port value, otherwise the host must - restore the port values itself (using lilv_state_get_port_value()) in order - to completely restore `state`. - - If the state has properties and `instance` is given, this function is in - the "instantiation" threading class, i.e. it MUST NOT be called - simultaneously with any function on the same plugin instance. If the state - has no properties, only port values are set via `set_value`. - - See state.h from the - LV2 State extension for details on the `flags` and `features` parameters. -*/ -LILV_API void -lilv_state_restore(const LilvState* state, - LilvInstance* instance, - LilvSetPortValueFunc set_value, - void* user_data, - uint32_t flags, - const LV2_Feature *const * features); - -/** - Save state to a file. - @param world The world. - @param map URID mapper. - @param unmap URID unmapper. - @param state State to save. - @param uri URI of state, may be NULL. - @param dir Path of the bundle directory to save into. - @param filename Path of the state file relative to `dir`. - - The format of state on disk is compatible with that defined in the LV2 - preset extension, i.e. this function may be used to save presets which can - be loaded by any host. - - If `uri` is NULL, the preset URI will be a file URI, but the bundle - can safely be moved (i.e. the state file will use "<>" as the subject). -*/ -LILV_API int -lilv_state_save(LilvWorld* world, - LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - const LilvState* state, - const char* uri, - const char* dir, - const char* filename); - -/** - Save state to a string. This function does not use the filesystem. - - @param world The world. - @param map URID mapper. - @param unmap URID unmapper. - @param state The state to serialize. - @param uri URI for the state description (mandatory). - @param base_uri Base URI for serialisation. Unless you know what you are - doing, pass NULL for this, otherwise the state may not be restorable via - lilv_state_new_from_string(). -*/ -LILV_API char* -lilv_state_to_string(LilvWorld* world, - LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - const LilvState* state, - const char* uri, - const char* base_uri); - -/** - Unload a state from the world and delete all associated files. - @param world The world. - @param state State to remove from the system. - - This function DELETES FILES/DIRECTORIES FROM THE FILESYSTEM! It is intended - for removing user-saved presets, but can delete any state the user has - permission to delete, including presets shipped with plugins. - - The rdfs:seeAlso file for the state will be removed. The entry in the - bundle's manifest.ttl is removed, and if this results in an empty manifest, - then the manifest file is removed. If this results in an empty bundle, then - the bundle directory is removed as well. -*/ -LILV_API int -lilv_state_delete(LilvWorld* world, - const LilvState* state); - -/** - @} - @name Scale Point - @{ -*/ - -/** - Get the label of this scale point (enumeration value) - Returned value is owned by `point` and must not be freed. -*/ -LILV_API const LilvNode* -lilv_scale_point_get_label(const LilvScalePoint* point); - -/** - Get the value of this scale point (enumeration value) - Returned value is owned by `point` and must not be freed. -*/ -LILV_API const LilvNode* -lilv_scale_point_get_value(const LilvScalePoint* point); - -/** - @} - @name Plugin Class - @{ -*/ - -/** - Get the URI of this class' superclass. - Returned value is owned by `plugin_class` and must not be freed by caller. - Returned value may be NULL, if class has no parent. -*/ -LILV_API const LilvNode* -lilv_plugin_class_get_parent_uri(const LilvPluginClass* plugin_class); - -/** - Get the URI of this plugin class. - Returned value is owned by `plugin_class` and must not be freed by caller. -*/ -LILV_API const LilvNode* -lilv_plugin_class_get_uri(const LilvPluginClass* plugin_class); - -/** - Get the label of this plugin class, ie "Oscillators". - Returned value is owned by `plugin_class` and must not be freed by caller. -*/ -LILV_API const LilvNode* -lilv_plugin_class_get_label(const LilvPluginClass* plugin_class); - -/** - Get the subclasses of this plugin class. - Returned value must be freed by caller with lilv_plugin_classes_free(). -*/ -LILV_API LilvPluginClasses* -lilv_plugin_class_get_children(const LilvPluginClass* plugin_class); - -/** - @} - @name Plugin Instance - @{ -*/ - -/** - @cond LILV_DOCUMENT_INSTANCE_IMPL -*/ - -/* Instance of a plugin. - This is exposed in the ABI to allow inlining of performance critical - functions like lilv_instance_run() (simple wrappers of functions in lv2.h). - This is for performance reasons, user code should not use this definition - in any way (which is why it is not machine documented). - Truly private implementation details are hidden via `pimpl`. -*/ -struct LilvInstanceImpl { - const LV2_Descriptor* lv2_descriptor; - LV2_Handle lv2_handle; - void* pimpl; -}; - -/** - @endcond -*/ - -/** - Instantiate a plugin. - The returned value is a lightweight handle for an LV2 plugin instance, - it does not refer to `plugin`, or any other Lilv state. The caller must - eventually free it with lilv_instance_free(). - `features` is a NULL-terminated array of features the host supports. - NULL may be passed if the host supports no additional features. - @return NULL if instantiation failed. -*/ -LILV_API LilvInstance* -lilv_plugin_instantiate(const LilvPlugin* plugin, - double sample_rate, - const LV2_Feature*const* features); - -/** - Free a plugin instance. - It is safe to call this function on NULL. - `instance` is invalid after this call. -*/ -LILV_API void -lilv_instance_free(LilvInstance* instance); - -#ifndef LILV_INTERNAL - -/** - Get the URI of the plugin which `instance` is an instance of. - Returned string is shared and must not be modified or deleted. -*/ -static inline const char* -lilv_instance_get_uri(const LilvInstance* instance) -{ - return instance->lv2_descriptor->URI; -} - -/** - Connect a port to a data location. - This may be called regardless of whether the plugin is activated, - activation and deactivation does not destroy port connections. -*/ -static inline void -lilv_instance_connect_port(LilvInstance* instance, - uint32_t port_index, - void* data_location) -{ - instance->lv2_descriptor->connect_port - (instance->lv2_handle, port_index, data_location); -} - -/** - Activate a plugin instance. - This resets all state information in the plugin, except for port data - locations (as set by lilv_instance_connect_port()). This MUST be called - before calling lilv_instance_run(). -*/ -static inline void -lilv_instance_activate(LilvInstance* instance) -{ - if (instance->lv2_descriptor->activate) - instance->lv2_descriptor->activate(instance->lv2_handle); -} - -/** - Run `instance` for `sample_count` frames. - If the hint lv2:hardRTCapable is set for this plugin, this function is - guaranteed not to block. -*/ -static inline void -lilv_instance_run(LilvInstance* instance, - uint32_t sample_count) -{ - instance->lv2_descriptor->run(instance->lv2_handle, sample_count); -} - -/** - Deactivate a plugin instance. - Note that to run the plugin after this you must activate it, which will - reset all state information (except port connections). -*/ -static inline void -lilv_instance_deactivate(LilvInstance* instance) -{ - if (instance->lv2_descriptor->deactivate) - instance->lv2_descriptor->deactivate(instance->lv2_handle); -} - -/** - Get extension data from the plugin instance. - The type and semantics of the data returned is specific to the particular - extension, though in all cases it is shared and must not be deleted. -*/ -static inline const void* -lilv_instance_get_extension_data(const LilvInstance* instance, - const char* uri) -{ - if (instance->lv2_descriptor->extension_data) - return instance->lv2_descriptor->extension_data(uri); - else - return NULL; -} - -/** - Get the LV2_Descriptor of the plugin instance. - Normally hosts should not need to access the LV2_Descriptor directly, - use the lilv_instance_* functions. - - The returned descriptor is shared and must not be deleted. -*/ -static inline const LV2_Descriptor* -lilv_instance_get_descriptor(const LilvInstance* instance) -{ - return instance->lv2_descriptor; -} - -/** - Get the LV2_Handle of the plugin instance. - Normally hosts should not need to access the LV2_Handle directly, - use the lilv_instance_* functions. - - The returned handle is shared and must not be deleted. -*/ -static inline LV2_Handle -lilv_instance_get_handle(const LilvInstance* instance) -{ - return instance->lv2_handle; -} - -#endif /* LILV_INTERNAL */ - -/** - @} - @name Plugin UI - @{ -*/ - -/** - Get all UIs for `plugin`. - Returned value must be freed by caller using lilv_uis_free(). -*/ -LILV_API LilvUIs* -lilv_plugin_get_uis(const LilvPlugin* plugin); - -/** - Get the URI of a Plugin UI. - @param ui The Plugin UI - @return a shared value which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_ui_get_uri(const LilvUI* ui); - -/** - Get the types (URIs of RDF classes) of a Plugin UI. - @param ui The Plugin UI - @return a shared value which must not be modified or freed. - - Note that in most cases lilv_ui_is_supported() should be used, which avoids - the need to use this function (and type specific logic). -*/ -LILV_API const LilvNodes* -lilv_ui_get_classes(const LilvUI* ui); - -/** - Check whether a plugin UI has a given type. - @param ui The Plugin UI - @param class_uri The URI of the LV2 UI type to check this UI against -*/ -LILV_API bool -lilv_ui_is_a(const LilvUI* ui, const LilvNode* class_uri); - -/** - Function to determine whether a UI type is supported. - - This is provided by the user and must return non-zero iff using a UI of type - `ui_type_uri` in a container of type `container_type_uri` is supported. -*/ -typedef unsigned (*LilvUISupportedFunc)(const char* container_type_uri, - const char* ui_type_uri); - -/** - Return true iff a Plugin UI is supported as a given widget type. - @param ui The Plugin UI - @param supported_func User provided supported predicate. - @param container_type The widget type to host the UI within. - @param ui_type (Output) If non-NULL, set to the native type of the UI - which is owned by `ui` and must not be freed by the caller. - @return The embedding quality level returned by `supported_func`. -*/ -LILV_API unsigned -lilv_ui_is_supported(const LilvUI* ui, - LilvUISupportedFunc supported_func, - const LilvNode* container_type, - const LilvNode** ui_type); - -/** - Get the URI for a Plugin UI's bundle. - @param ui The Plugin UI - @return a shared value which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_ui_get_bundle_uri(const LilvUI* ui); - -/** - Get the URI for a Plugin UI's shared library. - @param ui The Plugin UI - @return a shared value which must not be modified or freed. -*/ -LILV_API const LilvNode* -lilv_ui_get_binary_uri(const LilvUI* ui); - -/** - @} - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LILV_LILV_H */ diff --git a/source/modules/lilv/lilv-0.24.0/src/plugin.c.orig b/source/modules/lilv/lilv-0.24.0/src/plugin.c.orig deleted file mode 100644 index 5e10d7cf0..000000000 --- a/source/modules/lilv/lilv-0.24.0/src/plugin.c.orig +++ /dev/null @@ -1,1132 +0,0 @@ -/* - Copyright 2007-2016 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. -*/ - -#define __STDC_LIMIT_MACROS - -#include -#include -#include -#include -#include -#include -#include - -#include "lilv_config.h" -#include "lilv_internal.h" - -#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" - -#define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#" -#define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/" - -static void -lilv_plugin_init(LilvPlugin* plugin, LilvNode* bundle_uri) -{ - plugin->bundle_uri = bundle_uri; - plugin->binary_uri = NULL; -#ifdef LILV_DYN_MANIFEST - plugin->dynmanifest = NULL; -#endif - plugin->plugin_class = NULL; - plugin->data_uris = lilv_nodes_new(); - plugin->ports = NULL; - plugin->num_ports = 0; - plugin->loaded = false; - plugin->parse_errors = false; - plugin->replaced = false; -} - -/** Ownership of `uri` and `bundle` is taken */ -LilvPlugin* -lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) -{ - LilvPlugin* plugin = (LilvPlugin*)malloc(sizeof(LilvPlugin)); - - plugin->world = world; - plugin->plugin_uri = uri; - - lilv_plugin_init(plugin, bundle_uri); - return plugin; -} - -void -lilv_plugin_clear(LilvPlugin* plugin, LilvNode* bundle_uri) -{ - lilv_node_free(plugin->bundle_uri); - lilv_node_free(plugin->binary_uri); - lilv_nodes_free(plugin->data_uris); - lilv_plugin_init(plugin, bundle_uri); -} - -static void -lilv_plugin_free_ports(LilvPlugin* p) -{ - if (p->ports) { - for (uint32_t i = 0; i < p->num_ports; ++i) { - lilv_port_free(p, p->ports[i]); - } - free(p->ports); - p->num_ports = 0; - p->ports = NULL; - } -} - -void -lilv_plugin_free(LilvPlugin* p) -{ -#ifdef LILV_DYN_MANIFEST - if (p->dynmanifest && --p->dynmanifest->refs == 0) { - typedef int (*CloseFunc)(LV2_Dyn_Manifest_Handle); - CloseFunc close_func = (CloseFunc)lilv_dlfunc(p->dynmanifest->lib, - "lv2_dyn_manifest_close"); - if (close_func) { - close_func(p->dynmanifest->handle); - } - - dlclose(p->dynmanifest->lib); - lilv_node_free(p->dynmanifest->bundle); - free(p->dynmanifest); - } -#endif - - lilv_node_free(p->plugin_uri); - p->plugin_uri = NULL; - - lilv_node_free(p->bundle_uri); - p->bundle_uri = NULL; - - lilv_node_free(p->binary_uri); - p->binary_uri = NULL; - - lilv_plugin_free_ports(p); - - lilv_nodes_free(p->data_uris); - p->data_uris = NULL; - - free(p); -} - -static LilvNode* -lilv_plugin_get_one(const LilvPlugin* p, - const SordNode* subject, - const SordNode* predicate) -{ - LilvNode* ret = NULL; - SordIter* stream = lilv_world_query_internal( - p->world, subject, predicate, NULL); - if (!sord_iter_end(stream)) { - ret = lilv_node_new_from_node(p->world, - sord_iter_get_node(stream, SORD_OBJECT)); - } - sord_iter_free(stream); - return ret; -} - -LilvNode* -lilv_plugin_get_unique(const LilvPlugin* p, - const SordNode* subject, - const SordNode* predicate) -{ - LilvNode* ret = lilv_plugin_get_one(p, subject, predicate); - if (!ret) { - LILV_ERRORF("No value found for (%s %s ...) property\n", - sord_node_get_string(subject), - sord_node_get_string(predicate)); - } - return ret; -} - -static void -lilv_plugin_load(LilvPlugin* p) -{ - SordNode* bundle_uri_node = p->bundle_uri->node; - const SerdNode* bundle_uri_snode = sord_node_to_serd_node(bundle_uri_node); - - SerdEnv* env = serd_env_new(bundle_uri_snode); - SerdReader* reader = sord_new_reader(p->world->model, env, SERD_TURTLE, - bundle_uri_node); - - SordModel* prots = lilv_world_filter_model(p->world, - p->world->model, - p->plugin_uri->node, - p->world->uris.lv2_prototype, - NULL, NULL); - SordModel* skel = sord_new(p->world->world, SORD_SPO, false); - SordIter* iter = sord_begin(prots); - for (; !sord_iter_end(iter); sord_iter_next(iter)) { - const SordNode* t = sord_iter_get_node(iter, SORD_OBJECT); - LilvNode* prototype = lilv_node_new_from_node(p->world, t); - - lilv_world_load_resource(p->world, prototype); - - SordIter* statements = sord_search( - p->world->model, prototype->node, NULL, NULL, NULL); - FOREACH_MATCH(statements) { - SordQuad quad; - sord_iter_get(statements, quad); - quad[0] = p->plugin_uri->node; - sord_add(skel, quad); - } - - sord_iter_free(statements); - lilv_node_free(prototype); - } - sord_iter_free(iter); - - for (iter = sord_begin(skel); !sord_iter_end(iter); sord_iter_next(iter)) { - SordQuad quad; - sord_iter_get(iter, quad); - sord_add(p->world->model, quad); - } - sord_iter_free(iter); - sord_free(skel); - sord_free(prots); - - // Parse all the plugin's data files into RDF model - SerdStatus st = SERD_SUCCESS; - LILV_FOREACH(nodes, i, p->data_uris) { - const LilvNode* data_uri = lilv_nodes_get(p->data_uris, i); - - serd_env_set_base_uri(env, sord_node_to_serd_node(data_uri->node)); - st = lilv_world_load_file(p->world, reader, data_uri); - if (st > SERD_FAILURE) { - break; - } - } - - if (st > SERD_FAILURE) { - p->loaded = true; - p->parse_errors = true; - serd_reader_free(reader); - serd_env_free(env); - return; - } - -#ifdef LILV_DYN_MANIFEST - typedef void* LV2_Dyn_Manifest_Handle; - // Load and parse dynamic manifest data, if this is a library - if (p->dynmanifest) { - typedef int (*GetDataFunc)(LV2_Dyn_Manifest_Handle handle, - FILE* fp, - const char* uri); - GetDataFunc get_data_func = (GetDataFunc)lilv_dlfunc( - p->dynmanifest->lib, "lv2_dyn_manifest_get_data"); - if (get_data_func) { - const SordNode* bundle = p->dynmanifest->bundle->node; - serd_env_set_base_uri(env, sord_node_to_serd_node(bundle)); - FILE* fd = tmpfile(); - get_data_func(p->dynmanifest->handle, fd, - lilv_node_as_string(p->plugin_uri)); - rewind(fd); - serd_reader_add_blank_prefix( - reader, lilv_world_blank_node_prefix(p->world)); - serd_reader_read_file_handle( - reader, fd, (const uint8_t*)"(dyn-manifest)"); - fclose(fd); - } - } -#endif - serd_reader_free(reader); - serd_env_free(env); - - p->loaded = true; -} - -static bool -is_symbol(const char* str) -{ - for (const char* s = str; *s; ++s) { - if (!((*s >= 'a' && *s <= 'z') || - (*s >= 'A' && *s <= 'Z') || - (s > str && *s >= '0' && *s <= '9') || - *s == '_')) { - return false; - } - } - return true; -} - -static void -lilv_plugin_load_ports_if_necessary(const LilvPlugin* const_p) -{ - LilvPlugin* p = (LilvPlugin*)const_p; - - lilv_plugin_load_if_necessary(p); - - if (!p->ports) { - p->ports = (LilvPort**)malloc(sizeof(LilvPort*)); - p->ports[0] = NULL; - - SordIter* ports = lilv_world_query_internal( - p->world, - p->plugin_uri->node, - p->world->uris.lv2_port, - NULL); - - FOREACH_MATCH(ports) { - const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT); - LilvNode* index = lilv_plugin_get_unique( - p, port, p->world->uris.lv2_index); - LilvNode* symbol = lilv_plugin_get_unique( - p, port, p->world->uris.lv2_symbol); - - if (!lilv_node_is_string(symbol) || - !is_symbol((const char*)sord_node_get_string(symbol->node))) { - LILV_ERRORF("Plugin <%s> port symbol `%s' is invalid\n", - lilv_node_as_uri(p->plugin_uri), - lilv_node_as_string(symbol)); - lilv_node_free(symbol); - lilv_node_free(index); - lilv_plugin_free_ports(p); - break; - } - - if (!lilv_node_is_int(index)) { - LILV_ERRORF("Plugin <%s> port index is not an integer\n", - lilv_node_as_uri(p->plugin_uri)); - lilv_node_free(symbol); - lilv_node_free(index); - lilv_plugin_free_ports(p); - break; - } - - uint32_t this_index = lilv_node_as_int(index); - LilvPort* this_port = NULL; - if (p->num_ports > this_index) { - this_port = p->ports[this_index]; - } else { - p->ports = (LilvPort**)realloc( - p->ports, (this_index + 1) * sizeof(LilvPort*)); - memset(p->ports + p->num_ports, '\0', - (this_index - p->num_ports) * sizeof(LilvPort*)); - p->num_ports = this_index + 1; - } - - // Havn't seen this port yet, add it to array - if (!this_port) { - this_port = lilv_port_new(p->world, - port, - this_index, - lilv_node_as_string(symbol)); - p->ports[this_index] = this_port; - } - - SordIter* types = lilv_world_query_internal( - p->world, port, p->world->uris.rdf_a, NULL); - FOREACH_MATCH(types) { - const SordNode* type = sord_iter_get_node(types, SORD_OBJECT); - if (sord_node_get_type(type) == SORD_URI) { - zix_tree_insert( - (ZixTree*)this_port->classes, - lilv_node_new_from_node(p->world, type), NULL); - } else { - LILV_WARNF("Plugin <%s> port type is not a URI\n", - lilv_node_as_uri(p->plugin_uri)); - } - } - sord_iter_free(types); - - lilv_node_free(symbol); - lilv_node_free(index); - } - sord_iter_free(ports); - - // Check sanity - for (uint32_t i = 0; i < p->num_ports; ++i) { - if (!p->ports[i]) { - LILV_ERRORF("Plugin <%s> is missing port %d/%d\n", - lilv_node_as_uri(p->plugin_uri), i, p->num_ports); - lilv_plugin_free_ports(p); - break; - } - } - } -} - -void -lilv_plugin_load_if_necessary(const LilvPlugin* p) -{ - if (!p->loaded) - lilv_plugin_load((LilvPlugin*)p); -} - -LILV_API const LilvNode* -lilv_plugin_get_uri(const LilvPlugin* p) -{ - return p->plugin_uri; -} - -LILV_API const LilvNode* -lilv_plugin_get_bundle_uri(const LilvPlugin* p) -{ - return p->bundle_uri; -} - -LILV_API const LilvNode* -lilv_plugin_get_library_uri(const LilvPlugin* const_p) -{ - LilvPlugin* p = (LilvPlugin*)const_p; - lilv_plugin_load_if_necessary(p); - if (!p->binary_uri) { - // lv2:binary ?binary - SordIter* i = lilv_world_query_internal(p->world, - p->plugin_uri->node, - p->world->uris.lv2_binary, - NULL); - FOREACH_MATCH(i) { - const SordNode* binary_node = sord_iter_get_node(i, SORD_OBJECT); - if (sord_node_get_type(binary_node) == SORD_URI) { - p->binary_uri = lilv_node_new_from_node(p->world, binary_node); - break; - } - } - sord_iter_free(i); - } - if (!p->binary_uri) { - LILV_WARNF("Plugin <%s> has no lv2:binary\n", - lilv_node_as_uri(lilv_plugin_get_uri(p))); - } - return p->binary_uri; -} - -LILV_API const LilvNodes* -lilv_plugin_get_data_uris(const LilvPlugin* p) -{ - return p->data_uris; -} - -LILV_API const LilvPluginClass* -lilv_plugin_get_class(const LilvPlugin* const_p) -{ - LilvPlugin* p = (LilvPlugin*)const_p; - lilv_plugin_load_if_necessary(p); - if (!p->plugin_class) { - // a ?class - SordIter* c = lilv_world_query_internal(p->world, - p->plugin_uri->node, - p->world->uris.rdf_a, - NULL); - FOREACH_MATCH(c) { - const SordNode* class_node = sord_iter_get_node(c, SORD_OBJECT); - if (sord_node_get_type(class_node) != SORD_URI) { - continue; - } - - LilvNode* klass = lilv_node_new_from_node(p->world, class_node); - if (!lilv_node_equals(klass, p->world->lv2_plugin_class->uri)) { - const LilvPluginClass* pclass = lilv_plugin_classes_get_by_uri( - p->world->plugin_classes, klass); - - if (pclass) { - ((LilvPlugin*)p)->plugin_class = pclass; - lilv_node_free(klass); - break; - } - } - - lilv_node_free(klass); - } - sord_iter_free(c); - - if (p->plugin_class == NULL) - p->plugin_class = p->world->lv2_plugin_class; - } - return p->plugin_class; -} - -static LilvNodes* -lilv_plugin_get_value_internal(const LilvPlugin* p, - const SordNode* predicate) -{ - lilv_plugin_load_if_necessary(p); - return lilv_world_find_nodes_internal( - p->world, p->plugin_uri->node, predicate, NULL); -} - -LILV_API bool -lilv_plugin_verify(const LilvPlugin* plugin) -{ - lilv_plugin_load_if_necessary(plugin); - if (plugin->parse_errors) { - return false; - } - - LilvNode* rdf_type = lilv_new_uri(plugin->world, LILV_NS_RDF "type"); - LilvNodes* results = lilv_plugin_get_value(plugin, rdf_type); - lilv_node_free(rdf_type); - if (!results) { - return false; - } - - lilv_nodes_free(results); - results = lilv_plugin_get_value_internal(plugin, - plugin->world->uris.doap_name); - if (!results) { - return false; - } - - lilv_nodes_free(results); - LilvNode* lv2_port = lilv_new_uri(plugin->world, LV2_CORE__port); - results = lilv_plugin_get_value(plugin, lv2_port); - lilv_node_free(lv2_port); - if (!results) { - return false; - } - - lilv_nodes_free(results); - return true; -} - -LILV_API LilvNode* -lilv_plugin_get_name(const LilvPlugin* plugin) -{ - LilvNodes* results = lilv_plugin_get_value_internal( - plugin, plugin->world->uris.doap_name); - - LilvNode* ret = NULL; - if (results) { - LilvNode* val = lilv_nodes_get_first(results); - if (lilv_node_is_string(val)) - ret = lilv_node_duplicate(val); - lilv_nodes_free(results); - } - - if (!ret) - LILV_WARNF("Plugin <%s> has no (mandatory) doap:name\n", - lilv_node_as_string(lilv_plugin_get_uri(plugin))); - - return ret; -} - -LILV_API LilvNodes* -lilv_plugin_get_value(const LilvPlugin* p, - const LilvNode* predicate) -{ - lilv_plugin_load_if_necessary(p); - return lilv_world_find_nodes(p->world, p->plugin_uri, predicate, NULL); -} - -LILV_API uint32_t -lilv_plugin_get_num_ports(const LilvPlugin* p) -{ - lilv_plugin_load_ports_if_necessary(p); - return p->num_ports; -} - -LILV_API void -lilv_plugin_get_port_ranges_float(const LilvPlugin* p, - float* min_values, - float* max_values, - float* def_values) -{ - lilv_plugin_load_ports_if_necessary(p); - LilvNode* min = NULL; - LilvNode* max = NULL; - LilvNode* def = NULL; - LilvNode** minptr = min_values ? &min : NULL; - LilvNode** maxptr = max_values ? &max : NULL; - LilvNode** defptr = def_values ? &def : NULL; - - for (uint32_t i = 0; i < p->num_ports; ++i) { - lilv_port_get_range(p, p->ports[i], defptr, minptr, maxptr); - - if (min_values) { - if (lilv_node_is_float(min) || lilv_node_is_int(min)) { - min_values[i] = lilv_node_as_float(min); - } else { - min_values[i] = NAN; - } - } - - if (max_values) { - if (lilv_node_is_float(max) || lilv_node_is_int(max)) { - max_values[i] = lilv_node_as_float(max); - } else { - max_values[i] = NAN; - } - } - - if (def_values) { - if (lilv_node_is_float(def) || lilv_node_is_int(def)) { - def_values[i] = lilv_node_as_float(def); - } else { - def_values[i] = NAN; - } - } - - lilv_node_free(def); - lilv_node_free(min); - lilv_node_free(max); - } -} - -LILV_API uint32_t -lilv_plugin_get_num_ports_of_class_va(const LilvPlugin* p, - const LilvNode* class_1, - va_list args) -{ - lilv_plugin_load_ports_if_necessary(p); - - uint32_t count = 0; - - // Build array of classes from args so we can walk it several times - size_t n_classes = 0; - const LilvNode** classes = NULL; - for (LilvNode* c = NULL; (c = va_arg(args, LilvNode*)); ) { - classes = (const LilvNode**)realloc( - classes, ++n_classes * sizeof(LilvNode*)); - classes[n_classes - 1] = c; - } - - // Check each port against every type - for (unsigned i = 0; i < p->num_ports; ++i) { - LilvPort* port = p->ports[i]; - if (port && lilv_port_is_a(p, port, class_1)) { - bool matches = true; - for (size_t j = 0; j < n_classes; ++j) { - if (!lilv_port_is_a(p, port, classes[j])) { - matches = false; - break; - } - } - - if (matches) { - ++count; - } - } - } - - free(classes); - return count; -} - -LILV_API uint32_t -lilv_plugin_get_num_ports_of_class(const LilvPlugin* p, - const LilvNode* class_1, ...) -{ - va_list args; - va_start(args, class_1); - - uint32_t count = lilv_plugin_get_num_ports_of_class_va(p, class_1, args); - - va_end(args); - return count; -} - -LILV_API bool -lilv_plugin_has_latency(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - SordIter* ports = lilv_world_query_internal( - p->world, - p->plugin_uri->node, - p->world->uris.lv2_port, - NULL); - - bool ret = false; - FOREACH_MATCH(ports) { - const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT); - SordIter* prop = lilv_world_query_internal( - p->world, - port, - p->world->uris.lv2_portProperty, - p->world->uris.lv2_reportsLatency); - SordIter* des = lilv_world_query_internal( - p->world, - port, - p->world->uris.lv2_designation, - p->world->uris.lv2_latency); - const bool latent = !sord_iter_end(prop) || !sord_iter_end(des); - sord_iter_free(prop); - sord_iter_free(des); - if (latent) { - ret = true; - break; - } - } - sord_iter_free(ports); - - return ret; -} - -static const LilvPort* -lilv_plugin_get_port_by_property(const LilvPlugin* plugin, - const SordNode* port_property) -{ - lilv_plugin_load_ports_if_necessary(plugin); - for (uint32_t i = 0; i < plugin->num_ports; ++i) { - LilvPort* port = plugin->ports[i]; - SordIter* iter = lilv_world_query_internal( - plugin->world, - port->node->node, - plugin->world->uris.lv2_portProperty, - port_property); - - const bool found = !sord_iter_end(iter); - sord_iter_free(iter); - - if (found) { - return port; - } - } - - return NULL; -} - -LILV_API const LilvPort* -lilv_plugin_get_port_by_designation(const LilvPlugin* plugin, - const LilvNode* port_class, - const LilvNode* designation) -{ - LilvWorld* world = plugin->world; - lilv_plugin_load_ports_if_necessary(plugin); - for (uint32_t i = 0; i < plugin->num_ports; ++i) { - LilvPort* port = plugin->ports[i]; - SordIter* iter = lilv_world_query_internal( - world, - port->node->node, - world->uris.lv2_designation, - designation->node); - - const bool found = !sord_iter_end(iter) && - (!port_class || lilv_port_is_a(plugin, port, port_class)); - sord_iter_free(iter); - - if (found) { - return port; - } - } - - return NULL; -} - -LILV_API uint32_t -lilv_plugin_get_latency_port_index(const LilvPlugin* p) -{ - const LilvPort* prop_port = lilv_plugin_get_port_by_property( - p, p->world->uris.lv2_reportsLatency); - const LilvPort* des_port = lilv_plugin_get_port_by_property( - p, p->world->uris.lv2_latency); - if (prop_port) { - return prop_port->index; - } else if (des_port) { - return des_port->index; - } else { - return (uint32_t)-1; - } -} - -LILV_API bool -lilv_plugin_has_feature(const LilvPlugin* p, - const LilvNode* feature) -{ - lilv_plugin_load_if_necessary(p); - const SordNode* predicates[] = { p->world->uris.lv2_requiredFeature, - p->world->uris.lv2_optionalFeature, - NULL }; - - for (const SordNode** pred = predicates; *pred; ++pred) { - if (lilv_world_ask_internal( - p->world, p->plugin_uri->node, *pred, feature->node)) { - return true; - } - } - return false; -} - -LILV_API LilvNodes* -lilv_plugin_get_supported_features(const LilvPlugin* p) -{ - LilvNodes* optional = lilv_plugin_get_optional_features(p); - LilvNodes* required = lilv_plugin_get_required_features(p); - LilvNodes* result = lilv_nodes_merge(optional, required); - lilv_nodes_free(optional); - lilv_nodes_free(required); - return result; -} - -LILV_API LilvNodes* -lilv_plugin_get_optional_features(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - return lilv_world_find_nodes_internal(p->world, - p->plugin_uri->node, - p->world->uris.lv2_optionalFeature, - NULL); -} - -LILV_API LilvNodes* -lilv_plugin_get_required_features(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - return lilv_world_find_nodes_internal(p->world, - p->plugin_uri->node, - p->world->uris.lv2_requiredFeature, - NULL); -} - -LILV_API bool -lilv_plugin_has_extension_data(const LilvPlugin* p, - const LilvNode* uri) -{ - if (!lilv_node_is_uri(uri)) { - LILV_ERRORF("Extension data `%s' is not a URI\n", - sord_node_get_string(uri->node)); - return false; - } - - lilv_plugin_load_if_necessary(p); - return lilv_world_ask_internal( - p->world, - p->plugin_uri->node, - p->world->uris.lv2_extensionData, - uri->node); -} - -LILV_API LilvNodes* -lilv_plugin_get_extension_data(const LilvPlugin* p) -{ - return lilv_plugin_get_value_internal(p, p->world->uris.lv2_extensionData); -} - -LILV_API const LilvPort* -lilv_plugin_get_port_by_index(const LilvPlugin* p, - uint32_t index) -{ - lilv_plugin_load_ports_if_necessary(p); - if (index < p->num_ports) - return p->ports[index]; - else - return NULL; -} - -LILV_API const LilvPort* -lilv_plugin_get_port_by_symbol(const LilvPlugin* p, - const LilvNode* symbol) -{ - lilv_plugin_load_ports_if_necessary(p); - for (uint32_t i = 0; i < p->num_ports; ++i) { - LilvPort* port = p->ports[i]; - if (lilv_node_equals(port->symbol, symbol)) - return port; - } - - return NULL; -} - -LILV_API LilvNode* -lilv_plugin_get_project(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - - SordNode* lv2_project = sord_new_uri(p->world->world, - (const uint8_t*)LV2_CORE__project); - - SordIter* projects = lilv_world_query_internal(p->world, - p->plugin_uri->node, - lv2_project, - NULL); - - sord_node_free(p->world->world, lv2_project); - - if (sord_iter_end(projects)) { - sord_iter_free(projects); - return NULL; - } - - const SordNode* project = sord_iter_get_node(projects, SORD_OBJECT); - - sord_iter_free(projects); - return lilv_node_new_from_node(p->world, project); -} - -static const SordNode* -lilv_plugin_get_author(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - - SordNode* doap_maintainer = sord_new_uri( - p->world->world, NS_DOAP "maintainer"); - - SordIter* maintainers = lilv_world_query_internal( - p->world, - p->plugin_uri->node, - doap_maintainer, - NULL); - - if (sord_iter_end(maintainers)) { - sord_iter_free(maintainers); - - LilvNode* project = lilv_plugin_get_project(p); - if (!project) { - sord_node_free(p->world->world, doap_maintainer); - return NULL; - } - - maintainers = lilv_world_query_internal( - p->world, - project->node, - doap_maintainer, - NULL); - - lilv_node_free(project); - } - - sord_node_free(p->world->world, doap_maintainer); - - if (sord_iter_end(maintainers)) { - sord_iter_free(maintainers); - return NULL; - } - - const SordNode* author = sord_iter_get_node(maintainers, SORD_OBJECT); - - sord_iter_free(maintainers); - return author; -} - -static LilvNode* -lilv_plugin_get_author_property(const LilvPlugin* plugin, const uint8_t* uri) -{ - const SordNode* author = lilv_plugin_get_author(plugin); - if (author) { - SordWorld* sworld = plugin->world->world; - SordNode* pred = sord_new_uri(sworld, uri); - LilvNode* ret = lilv_plugin_get_one(plugin, author, pred); - sord_node_free(sworld, pred); - return ret; - } - return NULL; -} - -LILV_API LilvNode* -lilv_plugin_get_author_name(const LilvPlugin* plugin) -{ - return lilv_plugin_get_author_property(plugin, NS_FOAF "name"); -} - -LILV_API LilvNode* -lilv_plugin_get_author_email(const LilvPlugin* plugin) -{ - return lilv_plugin_get_author_property(plugin, NS_FOAF "mbox"); -} - -LILV_API LilvNode* -lilv_plugin_get_author_homepage(const LilvPlugin* plugin) -{ - return lilv_plugin_get_author_property(plugin, NS_FOAF "homepage"); -} - -LILV_API bool -lilv_plugin_is_replaced(const LilvPlugin* plugin) -{ - return plugin->replaced; -} - -LILV_API LilvUIs* -lilv_plugin_get_uis(const LilvPlugin* p) -{ - lilv_plugin_load_if_necessary(p); - - SordNode* ui_ui_node = sord_new_uri(p->world->world, - (const uint8_t*)LV2_UI__ui); - SordNode* ui_binary_node = sord_new_uri(p->world->world, - (const uint8_t*)LV2_UI__binary); - - LilvUIs* result = lilv_uis_new(); - SordIter* uis = lilv_world_query_internal(p->world, - p->plugin_uri->node, - ui_ui_node, - NULL); - - FOREACH_MATCH(uis) { - const SordNode* ui = sord_iter_get_node(uis, SORD_OBJECT); - - LilvNode* type = lilv_plugin_get_unique(p, ui, p->world->uris.rdf_a); - LilvNode* binary = lilv_plugin_get_one(p, ui, p->world->uris.lv2_binary); - if (!binary) { - binary = lilv_plugin_get_unique(p, ui, ui_binary_node); - } - - if (sord_node_get_type(ui) != SORD_URI - || !lilv_node_is_uri(type) - || !lilv_node_is_uri(binary)) { - lilv_node_free(binary); - lilv_node_free(type); - LILV_ERRORF("Corrupt UI <%s>\n", sord_node_get_string(ui)); - continue; - } - - LilvUI* lilv_ui = lilv_ui_new( - p->world, - lilv_node_new_from_node(p->world, ui), - type, - binary); - - zix_tree_insert((ZixTree*)result, lilv_ui, NULL); - } - sord_iter_free(uis); - - sord_node_free(p->world->world, ui_binary_node); - sord_node_free(p->world->world, ui_ui_node); - - if (lilv_uis_size(result) > 0) { - return result; - } else { - lilv_uis_free(result); - return NULL; - } -} - -LILV_API LilvNodes* -lilv_plugin_get_related(const LilvPlugin* plugin, const LilvNode* type) -{ - lilv_plugin_load_if_necessary(plugin); - - LilvWorld* const world = plugin->world; - LilvNodes* const related = lilv_world_find_nodes_internal( - world, - NULL, - world->uris.lv2_appliesTo, - lilv_plugin_get_uri(plugin)->node); - - if (!type) { - return related; - } - - LilvNodes* matches = lilv_nodes_new(); - LILV_FOREACH(nodes, i, related) { - LilvNode* node = (LilvNode*)lilv_collection_get((ZixTree*)related, i); - if (lilv_world_ask_internal( - world, node->node, world->uris.rdf_a, type->node)) { - zix_tree_insert((ZixTree*)matches, - lilv_node_new_from_node(world, node->node), - NULL); - } - } - - lilv_nodes_free(related); - return matches; -} - -static SerdEnv* -new_lv2_env(const SerdNode* base) -{ - SerdEnv* env = serd_env_new(base); - -#define USTR(s) ((const uint8_t*)s) - serd_env_set_prefix_from_strings(env, USTR("doap"), USTR(LILV_NS_DOAP)); - serd_env_set_prefix_from_strings(env, USTR("foaf"), USTR(LILV_NS_FOAF)); - serd_env_set_prefix_from_strings(env, USTR("lv2"), USTR(LILV_NS_LV2)); - serd_env_set_prefix_from_strings(env, USTR("owl"), USTR(LILV_NS_OWL)); - serd_env_set_prefix_from_strings(env, USTR("rdf"), USTR(LILV_NS_RDF)); - serd_env_set_prefix_from_strings(env, USTR("rdfs"), USTR(LILV_NS_RDFS)); - serd_env_set_prefix_from_strings(env, USTR("xsd"), USTR(LILV_NS_XSD)); - - return env; -} - -static void -maybe_write_prefixes(SerdWriter* writer, SerdEnv* env, FILE* file) -{ - fseek(file, 0, SEEK_END); - if (ftell(file) == 0) { - serd_env_foreach( - env, (SerdPrefixSink)serd_writer_set_prefix, writer); - } else { - fprintf(file, "\n"); - } -} - -LILV_API void -lilv_plugin_write_description(LilvWorld* world, - const LilvPlugin* plugin, - const LilvNode* base_uri, - FILE* plugin_file) -{ - const LilvNode* subject = lilv_plugin_get_uri(plugin); - const uint32_t num_ports = lilv_plugin_get_num_ports(plugin); - const SerdNode* base = sord_node_to_serd_node(base_uri->node); - SerdEnv* env = new_lv2_env(base); - - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), - env, - NULL, - serd_file_sink, - plugin_file); - - // Write prefixes if this is a new file - maybe_write_prefixes(writer, env, plugin_file); - - // Write plugin description - SordIter* plug_iter = lilv_world_query_internal( - world, subject->node, NULL, NULL); - sord_write_iter(plug_iter, writer); - - // Write port descriptions - for (uint32_t i = 0; i < num_ports; ++i) { - const LilvPort* port = plugin->ports[i]; - SordIter* port_iter = lilv_world_query_internal( - world, port->node->node, NULL, NULL); - sord_write_iter(port_iter, writer); - } - - serd_writer_free(writer); - serd_env_free(env); -} - -LILV_API void -lilv_plugin_write_manifest_entry(LilvWorld* world, - const LilvPlugin* plugin, - const LilvNode* base_uri, - FILE* manifest_file, - const char* plugin_file_path) -{ - const LilvNode* subject = lilv_plugin_get_uri(plugin); - const SerdNode* base = sord_node_to_serd_node(base_uri->node); - SerdEnv* env = new_lv2_env(base); - - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_ABBREVIATED|SERD_STYLE_CURIED), - env, - NULL, - serd_file_sink, - manifest_file); - - // Write prefixes if this is a new file - maybe_write_prefixes(writer, env, manifest_file); - - // Write manifest entry - serd_writer_write_statement( - writer, 0, NULL, - sord_node_to_serd_node(subject->node), - sord_node_to_serd_node(plugin->world->uris.rdf_a), - sord_node_to_serd_node(plugin->world->uris.lv2_Plugin), 0, 0); - - const SerdNode file_node = serd_node_from_string( - SERD_URI, (const uint8_t*)plugin_file_path); - serd_writer_write_statement( - writer, 0, NULL, - sord_node_to_serd_node(subject->node), - sord_node_to_serd_node(plugin->world->uris.rdfs_seeAlso), - &file_node, 0, 0); - - serd_writer_free(writer); - serd_env_free(env); -} diff --git a/source/modules/lilv/lilv-0.24.0/src/state.c.orig b/source/modules/lilv/lilv-0.24.0/src/state.c.orig deleted file mode 100644 index 478140582..000000000 --- a/source/modules/lilv/lilv-0.24.0/src/state.c.orig +++ /dev/null @@ -1,1329 +0,0 @@ -/* - Copyright 2007-2016 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 "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/atom/forge.h" -#include "lv2/lv2plug.in/ns/ext/presets/presets.h" -#include "lv2/lv2plug.in/ns/ext/state/state.h" - -#include "lilv_config.h" -#include "lilv_internal.h" -#include "sratom/sratom.h" - -#define USTR(s) ((const uint8_t*)(s)) - -typedef struct { - void* value; ///< Value/Object - size_t size; ///< Size of value - uint32_t key; ///< Key/Predicate (URID) - uint32_t type; ///< Type of value (URID) - uint32_t flags; ///< State flags (POD, etc) -} Property; - -typedef struct { - char* symbol; ///< Symbol of port - void* value; ///< Value of port - uint32_t size; ///< Size of value - uint32_t type; ///< Type of value (URID) -} PortValue; - -typedef struct { - char* abs; ///< Absolute path of actual file - char* rel; ///< Abstract path (relative path in state dir) -} PathMap; - -typedef struct { - size_t n; - Property* props; -} PropertyArray; - -struct LilvStateImpl { - LilvNode* plugin_uri; ///< Plugin URI - LilvNode* uri; ///< State/preset URI - char* dir; ///< Save directory (if saved) - char* file_dir; ///< Directory for files created by plugin - char* copy_dir; ///< Directory for snapshots of external files - char* link_dir; ///< Directory for links to external files - char* label; ///< State/Preset label - ZixTree* abs2rel; ///< PathMap sorted by abs - ZixTree* rel2abs; ///< PathMap sorted by rel - PropertyArray props; ///< State properties - PropertyArray metadata; ///< State metadata - PortValue* values; ///< Port values - uint32_t atom_Path; ///< atom:Path URID - uint32_t n_values; ///< Number of port values -}; - -static int -abs_cmp(const void* a, const void* b, void* user_data) -{ - return strcmp(((const PathMap*)a)->abs, ((const PathMap*)b)->abs); -} - -static int -rel_cmp(const void* a, const void* b, void* user_data) -{ - return strcmp(((const PathMap*)a)->rel, ((const PathMap*)b)->rel); -} - -static int -property_cmp(const void* a, const void* b) -{ - return ((const Property*)a)->key - ((const Property*)b)->key; -} - -static int -value_cmp(const void* a, const void* b) -{ - return strcmp(((const PortValue*)a)->symbol, - ((const PortValue*)b)->symbol); -} - -static void -path_rel_free(void* ptr) -{ - free(((PathMap*)ptr)->abs); - free(((PathMap*)ptr)->rel); - free(ptr); -} - -static PortValue* -append_port_value(LilvState* state, - const char* port_symbol, - const void* value, - uint32_t size, - uint32_t type) -{ - PortValue* pv = NULL; - if (value) { - state->values = (PortValue*)realloc( - state->values, (++state->n_values) * sizeof(PortValue)); - pv = &state->values[state->n_values - 1]; - pv->symbol = lilv_strdup(port_symbol); - pv->value = malloc(size); - pv->size = size; - pv->type = type; - memcpy(pv->value, value, size); - } - return pv; -} - -static const char* -lilv_state_rel2abs(const LilvState* state, const char* path) -{ - ZixTreeIter* iter = NULL; - const PathMap key = { NULL, (char*)path }; - if (state->rel2abs && !zix_tree_find(state->rel2abs, &key, &iter)) { - return ((const PathMap*)zix_tree_get(iter))->abs; - } - return path; -} - -static void -append_property(LilvState* state, - PropertyArray* array, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags) -{ - array->props = (Property*)realloc( - array->props, (++array->n) * sizeof(Property)); - - Property* const prop = &array->props[array->n - 1]; - if ((flags & LV2_STATE_IS_POD) || type == state->atom_Path) { - prop->value = malloc(size); - memcpy(prop->value, value, size); - } else { - prop->value = (void*)value; - } - - prop->size = size; - prop->key = key; - prop->type = type; - prop->flags = flags; -} - -static LV2_State_Status -store_callback(LV2_State_Handle handle, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags) -{ - LilvState* const state = (LilvState*)handle; - append_property(state, &state->props, key, value, size, type, flags); - return LV2_STATE_SUCCESS; -} - -static const void* -retrieve_callback(LV2_State_Handle handle, - uint32_t key, - size_t* size, - uint32_t* type, - uint32_t* flags) -{ - const LilvState* const state = (LilvState*)handle; - const Property search_key = { NULL, 0, key, 0, 0 }; - const Property* const prop = (Property*)bsearch( - &search_key, state->props.props, state->props.n, - sizeof(Property), property_cmp); - - if (prop) { - *size = prop->size; - *type = prop->type; - *flags = prop->flags; - return prop->value; - } - return NULL; -} - -static bool -lilv_state_has_path(const char* path, void* state) -{ - return lilv_state_rel2abs((LilvState*)state, path) != path; -} - -static char* -make_path(LV2_State_Make_Path_Handle handle, const char* path) -{ - LilvState* state = (LilvState*)handle; - if (!lilv_path_exists(state->dir, NULL)) { - lilv_mkdir_p(state->dir); - } - - return lilv_path_join(state->dir, path); -} - -static char* -abstract_path(LV2_State_Map_Path_Handle handle, - const char* abs_path) -{ - LilvState* state = (LilvState*)handle; - char* path = NULL; - char* real_path = lilv_realpath(abs_path); - const PathMap key = { (char*)real_path, NULL }; - ZixTreeIter* iter = NULL; - - if (abs_path[0] == '\0') { - return lilv_strdup(abs_path); - } else if (!zix_tree_find(state->abs2rel, &key, &iter)) { - // Already mapped path in a previous call - PathMap* pm = (PathMap*)zix_tree_get(iter); - free(real_path); - return lilv_strdup(pm->rel); - } else if (lilv_path_is_child(real_path, state->dir)) { - // File in state directory (loaded, or created by plugin during save) - path = lilv_path_relative_to(real_path, state->dir); - } else if (lilv_path_is_child(real_path, state->file_dir)) { - // File created by plugin earlier - path = lilv_path_relative_to(real_path, state->file_dir); - if (state->copy_dir) { - if (!lilv_path_exists(state->copy_dir, NULL)) { - lilv_mkdir_p(state->copy_dir); - } - char* cpath = lilv_path_join(state->copy_dir, path); - char* copy = lilv_get_latest_copy(real_path, cpath); - if (!copy || !lilv_file_equals(real_path, copy)) { - // No recent enough copy, make a new one - free(copy); - copy = lilv_find_free_path(cpath, lilv_path_exists, NULL); - const int st = lilv_copy_file(real_path, copy); - if (st) { - LILV_ERRORF("Error copying state file %s (%s)\n", - copy, strerror(st)); - } - } - free(real_path); - free(cpath); - - // Refer to the latest copy in plugin state - real_path = copy; - } - } else if (state->link_dir) { - // New path outside state directory, make a link - const char* slash = strrchr(real_path, '/'); - const char* name = slash ? (slash + 1) : real_path; - - // Find a free name in the (virtual) state directory - path = lilv_find_free_path(name, lilv_state_has_path, state); - } else { - // No link directory, preserve absolute path - path = lilv_strdup(abs_path); - } - - // Add record to path mapping - PathMap* pm = (PathMap*)malloc(sizeof(PathMap)); - pm->abs = real_path; - pm->rel = lilv_strdup(path); - zix_tree_insert(state->abs2rel, pm, NULL); - zix_tree_insert(state->rel2abs, pm, NULL); - - return path; -} - -static char* -absolute_path(LV2_State_Map_Path_Handle handle, - const char* state_path) -{ - LilvState* state = (LilvState*)handle; - char* path = NULL; - if (lilv_path_is_absolute(state_path)) { - // Absolute path, return identical path - path = lilv_strdup(state_path); - } else if (state->dir) { - // Relative path inside state directory - path = lilv_path_join(state->dir, state_path); - } else { - // State has not been saved, unmap - path = lilv_strdup(lilv_state_rel2abs(state, state_path)); - } - - return path; -} - -/** Return a new features array which is `feature` added to `features`. */ -static const LV2_Feature** -add_features(const LV2_Feature *const * features, - const LV2_Feature* map, const LV2_Feature* make) -{ - 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*)); - - if (features) { - memcpy(ret, features, n_features * sizeof(LV2_Feature*)); - } - - ret[n_features] = map; - ret[n_features + 1] = make; - return ret; -} - -static char* -absolute_dir(const char* path) -{ - char* abs_path = lilv_path_absolute(path); - char* base = lilv_path_join(abs_path, NULL); - free(abs_path); - return base; -} - -static const char* -state_strerror(LV2_State_Status st) -{ - switch (st) { - case LV2_STATE_SUCCESS: return "Completed successfully"; - case LV2_STATE_ERR_BAD_TYPE: return "Unsupported type"; - case LV2_STATE_ERR_BAD_FLAGS: return "Unsupported flags"; - case LV2_STATE_ERR_NO_FEATURE: return "Missing features"; - case LV2_STATE_ERR_NO_PROPERTY: return "Missing property"; - default: return "Unknown error"; - } -} - -LILV_API LilvState* -lilv_state_new_from_instance(const LilvPlugin* plugin, - LilvInstance* instance, - LV2_URID_Map* map, - const char* file_dir, - const char* copy_dir, - const char* link_dir, - const char* save_dir, - LilvGetPortValueFunc get_value, - void* user_data, - uint32_t flags, - const LV2_Feature *const * features) -{ - const LV2_Feature** sfeatures = NULL; - LilvWorld* const world = plugin->world; - LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState)); - state->plugin_uri = lilv_node_duplicate(lilv_plugin_get_uri(plugin)); - state->abs2rel = zix_tree_new(false, abs_cmp, NULL, path_rel_free); - state->rel2abs = zix_tree_new(false, rel_cmp, NULL, NULL); - state->file_dir = file_dir ? absolute_dir(file_dir) : NULL; - state->copy_dir = copy_dir ? absolute_dir(copy_dir) : NULL; - state->link_dir = link_dir ? absolute_dir(link_dir) : NULL; - state->dir = save_dir ? absolute_dir(save_dir) : NULL; - state->atom_Path = map->map(map->handle, LV2_ATOM__Path); - - LV2_State_Map_Path pmap = { state, abstract_path, absolute_path }; - LV2_Feature pmap_feature = { LV2_STATE__mapPath, &pmap }; - LV2_State_Make_Path pmake = { state, make_path }; - LV2_Feature pmake_feature = { LV2_STATE__makePath, &pmake }; - features = sfeatures = add_features(features, &pmap_feature, - save_dir ? &pmake_feature : NULL); - - // Store port values - if (get_value) { - LilvNode* lv2_ControlPort = lilv_new_uri(world, LILV_URI_CONTROL_PORT); - LilvNode* lv2_InputPort = lilv_new_uri(world, LILV_URI_INPUT_PORT); - for (uint32_t i = 0; i < plugin->num_ports; ++i) { - const LilvPort* const port = plugin->ports[i]; - if (lilv_port_is_a(plugin, port, lv2_ControlPort) - && lilv_port_is_a(plugin, port, lv2_InputPort)) { - uint32_t size, type; - const char* sym = lilv_node_as_string(port->symbol); - const void* value = get_value(sym, user_data, &size, &type); - append_port_value(state, sym, value, size, type); - } - } - lilv_node_free(lv2_ControlPort); - lilv_node_free(lv2_InputPort); - } - - // Store properties - const LV2_Descriptor* desc = instance->lv2_descriptor; - const LV2_State_Interface* iface = (desc->extension_data) - ? (const LV2_State_Interface*)desc->extension_data(LV2_STATE__interface) - : NULL; - - if (iface) { - LV2_State_Status st = iface->save( - instance->lv2_handle, store_callback, state, flags, features); - if (st) { - LILV_ERRORF("Error saving plugin state: %s\n", state_strerror(st)); - free(state->props.props); - state->props.props = NULL; - state->props.n = 0; - } else { - qsort(state->props.props, state->props.n, sizeof(Property), property_cmp); - } - } - - qsort(state->values, state->n_values, sizeof(PortValue), value_cmp); - - free(sfeatures); - return state; -} - -LILV_API void -lilv_state_emit_port_values(const LilvState* state, - LilvSetPortValueFunc set_value, - void* user_data) -{ - for (uint32_t i = 0; i < state->n_values; ++i) { - const PortValue* val = &state->values[i]; - set_value(val->symbol, user_data, val->value, val->size, val->type); - } -} - -LILV_API void -lilv_state_restore(const LilvState* state, - LilvInstance* instance, - LilvSetPortValueFunc set_value, - void* user_data, - uint32_t flags, - const LV2_Feature *const * features) -{ - if (!state) { - LILV_ERROR("lilv_state_restore() called on NULL state\n"); - return; - } - - LV2_State_Map_Path map_path = { - (LilvState*)state, abstract_path, absolute_path }; - LV2_Feature map_feature = { LV2_STATE__mapPath, &map_path }; - - if (instance) { - const LV2_Descriptor* desc = instance->lv2_descriptor; - if (desc->extension_data) { - const LV2_State_Interface* iface = (const LV2_State_Interface*) - desc->extension_data(LV2_STATE__interface); - - if (iface && iface->restore) { - const LV2_Feature** sfeatures = add_features( - features, &map_feature, NULL); - - iface->restore(instance->lv2_handle, retrieve_callback, - (LV2_State_Handle)state, flags, sfeatures); - - free(sfeatures); - } - } - } - - - if (set_value) { - lilv_state_emit_port_values(state, set_value, user_data); - } -} - -static LilvState* -new_state_from_model(LilvWorld* world, - LV2_URID_Map* map, - SordModel* model, - const SordNode* node, - const char* dir) -{ - // Check that we know at least something about this state subject - if (!sord_ask(model, node, 0, 0, 0)) { - return NULL; - } - - // Allocate state - LilvState* const state = (LilvState*)calloc(1, sizeof(LilvState)); - state->dir = lilv_strdup(dir); - state->atom_Path = map->map(map->handle, LV2_ATOM__Path); - state->uri = lilv_node_new_from_node(world, node); - - // Get the plugin URI this state applies to - SordIter* i = sord_search(model, node, world->uris.lv2_appliesTo, 0, 0); - if (i) { - const SordNode* object = sord_iter_get_node(i, SORD_OBJECT); - const SordNode* graph = sord_iter_get_node(i, SORD_GRAPH); - state->plugin_uri = lilv_node_new_from_node(world, object); - if (!state->dir && graph) { - state->dir = lilv_strdup((const char*)sord_node_get_string(graph)); - } - sord_iter_free(i); - } else if (sord_ask(model, - node, - world->uris.rdf_a, - world->uris.lv2_Plugin, 0)) { - // Loading plugin description as state (default state) - state->plugin_uri = lilv_node_new_from_node(world, node); - } else { - LILV_ERRORF("State %s missing lv2:appliesTo property\n", - sord_node_get_string(node)); - } - - // Get the state label - i = sord_search(model, node, world->uris.rdfs_label, NULL, NULL); - if (i) { - const SordNode* object = sord_iter_get_node(i, SORD_OBJECT); - const SordNode* graph = sord_iter_get_node(i, SORD_GRAPH); - state->label = lilv_strdup((const char*)sord_node_get_string(object)); - if (!state->dir && graph) { - state->dir = lilv_strdup((const char*)sord_node_get_string(graph)); - } - sord_iter_free(i); - } - - Sratom* sratom = sratom_new(map); - SerdChunk chunk = { NULL, 0 }; - LV2_Atom_Forge forge; - lv2_atom_forge_init(&forge, map); - lv2_atom_forge_set_sink( - &forge, sratom_forge_sink, sratom_forge_deref, &chunk); - - // Get port values - SordIter* ports = sord_search(model, node, world->uris.lv2_port, 0, 0); - FOREACH_MATCH(ports) { - const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT); - - SordNode* label = sord_get(model, port, world->uris.rdfs_label, 0, 0); - SordNode* symbol = sord_get(model, port, world->uris.lv2_symbol, 0, 0); - SordNode* value = sord_get(model, port, world->uris.pset_value, 0, 0); - if (!value) { - value = sord_get(model, port, world->uris.lv2_default, 0, 0); - } - if (!symbol) { - LILV_ERRORF("State `%s' port missing symbol.\n", - sord_node_get_string(node)); - } else if (value) { - chunk.len = 0; - sratom_read(sratom, &forge, world->world, model, value); - const LV2_Atom* atom = (const LV2_Atom*)chunk.buf; - - append_port_value(state, - (const char*)sord_node_get_string(symbol), - LV2_ATOM_BODY_CONST(atom), - atom->size, atom->type); - - if (label) { - lilv_state_set_label(state, - (const char*)sord_node_get_string(label)); - } - } - sord_node_free(world->world, value); - sord_node_free(world->world, symbol); - sord_node_free(world->world, label); - } - sord_iter_free(ports); - - // Get properties - SordNode* statep = sord_new_uri(world->world, USTR(LV2_STATE__state)); - SordNode* state_node = sord_get(model, node, statep, NULL, NULL); - if (state_node) { - SordIter* props = sord_search(model, state_node, 0, 0, 0); - FOREACH_MATCH(props) { - const SordNode* p = sord_iter_get_node(props, SORD_PREDICATE); - const SordNode* o = sord_iter_get_node(props, SORD_OBJECT); - const char* key = (const char*)sord_node_get_string(p); - - chunk.len = 0; - lv2_atom_forge_set_sink( - &forge, sratom_forge_sink, sratom_forge_deref, &chunk); - - sratom_read(sratom, &forge, world->world, model, o); - const LV2_Atom* atom = (const LV2_Atom*)chunk.buf; - uint32_t flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; - Property prop = { NULL, 0, 0, 0, flags }; - - prop.key = map->map(map->handle, key); - prop.type = atom->type; - prop.size = atom->size; - prop.value = malloc(atom->size); - memcpy(prop.value, LV2_ATOM_BODY_CONST(atom), atom->size); - if (atom->type == forge.Path) { - prop.flags = LV2_STATE_IS_POD; - } - - if (prop.value) { - state->props.props = (Property*)realloc( - state->props.props, (++state->props.n) * sizeof(Property)); - state->props.props[state->props.n - 1] = prop; - } - } - sord_iter_free(props); - } - sord_node_free(world->world, state_node); - sord_node_free(world->world, statep); - - free((void*)chunk.buf); - sratom_free(sratom); - - if (state->props.props) { - qsort(state->props.props, state->props.n, sizeof(Property), property_cmp); - } - if (state->values) { - qsort(state->values, state->n_values, sizeof(PortValue), value_cmp); - } - - return state; -} - -LILV_API LilvState* -lilv_state_new_from_world(LilvWorld* world, - LV2_URID_Map* map, - const LilvNode* node) -{ - if (!lilv_node_is_uri(node) && !lilv_node_is_blank(node)) { - LILV_ERRORF("Subject `%s' is not a URI or blank node.\n", - lilv_node_as_string(node)); - return NULL; - } - - return new_state_from_model(world, map, world->model, node->node, NULL); -} - -LILV_API LilvState* -lilv_state_new_from_file(LilvWorld* world, - LV2_URID_Map* map, - const LilvNode* subject, - const char* path) -{ - if (subject && !lilv_node_is_uri(subject) - && !lilv_node_is_blank(subject)) { - LILV_ERRORF("Subject `%s' is not a URI or blank node.\n", - lilv_node_as_string(subject)); - return NULL; - } - - uint8_t* abs_path = (uint8_t*)lilv_path_absolute(path); - SerdNode node = serd_node_new_file_uri(abs_path, NULL, NULL, 0); - SerdEnv* env = serd_env_new(&node); - SordModel* model = sord_new(world->world, SORD_SPO, false); - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - - serd_reader_read_file(reader, node.buf); - - SordNode* subject_node = (subject) - ? subject->node - : sord_node_from_serd_node(world->world, env, &node, NULL, NULL); - - char* dirname = lilv_dirname(path); - char* real_path = lilv_realpath(dirname); - LilvState* state = new_state_from_model( - world, map, model, subject_node, real_path); - free(dirname); - free(real_path); - - serd_node_free(&node); - free(abs_path); - serd_reader_free(reader); - sord_free(model); - serd_env_free(env); - return state; -} - -static void -set_prefixes(SerdEnv* env) -{ -#define SET_PSET(e, p, u) serd_env_set_prefix_from_strings(e, p, u) - SET_PSET(env, USTR("atom"), USTR(LV2_ATOM_PREFIX)); - SET_PSET(env, USTR("lv2"), USTR(LV2_CORE_PREFIX)); - SET_PSET(env, USTR("pset"), USTR(LV2_PRESETS_PREFIX)); - SET_PSET(env, USTR("rdf"), USTR(LILV_NS_RDF)); - SET_PSET(env, USTR("rdfs"), USTR(LILV_NS_RDFS)); - SET_PSET(env, USTR("state"), USTR(LV2_STATE_PREFIX)); - SET_PSET(env, USTR("xsd"), USTR(LILV_NS_XSD)); -} - -LILV_API LilvState* -lilv_state_new_from_string(LilvWorld* world, - LV2_URID_Map* map, - const char* str) -{ - if (!str) { - return NULL; - } - - SerdNode base = SERD_NODE_NULL; - SerdEnv* env = serd_env_new(&base); - SordModel* model = sord_new(world->world, SORD_SPO|SORD_OPS, false); - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - - set_prefixes(env); - serd_reader_read_string(reader, USTR(str)); - - SordNode* o = sord_new_uri(world->world, USTR(LV2_PRESETS__Preset)); - SordNode* s = sord_get(model, NULL, world->uris.rdf_a, o, NULL); - - LilvState* state = new_state_from_model(world, map, model, s, NULL); - - sord_node_free(world->world, s); - sord_node_free(world->world, o); - serd_reader_free(reader); - sord_free(model); - serd_env_free(env); - - return state; -} - -static SerdWriter* -ttl_writer(SerdSink sink, void* stream, const SerdNode* base, SerdEnv** new_env) -{ - SerdURI base_uri = SERD_URI_NULL; - if (base && base->buf) { - serd_uri_parse(base->buf, &base_uri); - } - - SerdEnv* env = *new_env ? *new_env : serd_env_new(base); - set_prefixes(env); - - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, - (SerdStyle)(SERD_STYLE_RESOLVED | - SERD_STYLE_ABBREVIATED| - SERD_STYLE_CURIED), - env, - &base_uri, - sink, - stream); - - if (!*new_env) { - *new_env = env; - } - - return writer; -} - -static SerdWriter* -ttl_file_writer(FILE* fd, const SerdNode* node, SerdEnv** env) -{ - SerdWriter* writer = ttl_writer(serd_file_sink, fd, node, env); - - fseek(fd, 0, SEEK_END); - if (ftell(fd) == 0) { - serd_env_foreach(*env, (SerdPrefixSink)serd_writer_set_prefix, writer); - } else { - fprintf(fd, "\n"); - } - - return writer; -} - -static void -add_to_model(SordWorld* world, - SerdEnv* env, - SordModel* model, - const SerdNode s, - const SerdNode p, - const SerdNode o) -{ - SordNode* ss = sord_node_from_serd_node(world, env, &s, NULL, NULL); - SordNode* sp = sord_node_from_serd_node(world, env, &p, NULL, NULL); - SordNode* so = sord_node_from_serd_node(world, env, &o, NULL, NULL); - - SordQuad quad = { ss, sp, so, NULL }; - sord_add(model, quad); - - sord_node_free(world, ss); - sord_node_free(world, sp); - sord_node_free(world, so); -} - -static void -remove_manifest_entry(SordWorld* world, SordModel* model, const char* subject) -{ - SordNode* s = sord_new_uri(world, USTR(subject)); - SordIter* i = sord_search(model, s, NULL, NULL, NULL); - while (!sord_iter_end(i)) { - sord_erase(model, i); - } - sord_iter_free(i); - sord_node_free(world, s); -} - -static int -add_state_to_manifest(LilvWorld* lworld, - const LilvNode* plugin_uri, - const char* manifest_path, - const char* state_uri, - const char* state_path) -{ - SordWorld* world = lworld->world; - SerdNode manifest = serd_node_new_file_uri(USTR(manifest_path), 0, 0, 0); - SerdNode file = serd_node_new_file_uri(USTR(state_path), 0, 0, 0); - SerdEnv* env = serd_env_new(&manifest); - SordModel* model = sord_new(world, SORD_SPO, false); - - FILE* rfd = fopen(manifest_path, "r"); - if (rfd) { - // Read manifest into model - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - lilv_flock(rfd, true); - serd_reader_read_file_handle(reader, rfd, manifest.buf); - serd_reader_free(reader); - } - - // Choose state URI (use file URI if not given) - if (!state_uri) { - state_uri = (const char*)file.buf; - } - - // Remove any existing manifest entries for this state - remove_manifest_entry(world, model, state_uri); - - // Add manifest entry for this state to model - SerdNode s = serd_node_from_string(SERD_URI, USTR(state_uri)); - - // a pset:Preset - add_to_model(world, env, model, - s, - serd_node_from_string(SERD_URI, USTR(LILV_NS_RDF "type")), - serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__Preset))); - - // a pset:Preset - add_to_model(world, env, model, - s, - serd_node_from_string(SERD_URI, USTR(LILV_NS_RDF "type")), - serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__Preset))); - - // rdfs:seeAlso - add_to_model(world, env, model, - s, - serd_node_from_string(SERD_URI, USTR(LILV_NS_RDFS "seeAlso")), - file); - - // lv2:appliesTo - add_to_model(world, env, model, - s, - serd_node_from_string(SERD_URI, USTR(LV2_CORE__appliesTo)), - serd_node_from_string(SERD_URI, - USTR(lilv_node_as_string(plugin_uri)))); - - // Write manifest model to file - FILE* wfd = fopen(manifest_path, "w"); - if (wfd) { - SerdWriter* writer = ttl_file_writer(wfd, &manifest, &env); - sord_write(model, writer, NULL); - serd_writer_free(writer); - fclose(wfd); - } else { - LILV_ERRORF("Failed to open %s for writing (%s)\n", - manifest_path, strerror(errno)); - } - - sord_free(model); - serd_node_free(&file); - serd_node_free(&manifest); - serd_env_free(env); - - if (rfd) { - lilv_flock(rfd, false); - fclose(rfd); - } - - return 0; -} - -static bool -link_exists(const char* path, void* data) -{ - const char* target = (const char*)data; - if (!lilv_path_exists(path, NULL)) { - return false; - } - char* real_path = lilv_realpath(path); - bool matches = !strcmp(real_path, target); - free(real_path); - return !matches; -} - -static void -write_property_array(const LilvState* state, - const PropertyArray* array, - Sratom* sratom, - uint32_t flags, - const SerdNode* subject, - LV2_URID_Unmap* unmap, - const char* dir) -{ - for (uint32_t i = 0; i < array->n; ++i) { - Property* prop = &array->props[i]; - const char* key = unmap->unmap(unmap->handle, prop->key); - - const SerdNode p = serd_node_from_string(SERD_URI, USTR(key)); - if (prop->type == state->atom_Path && !dir) { - const char* path = (const char*)prop->value; - const char* abs_path = lilv_state_rel2abs(state, path); - LILV_WARNF("Writing absolute path %s\n", abs_path); - sratom_write(sratom, unmap, flags, - subject, &p, prop->type, - strlen(abs_path) + 1, abs_path); - } else if (prop->flags & LV2_STATE_IS_POD || - prop->type == state->atom_Path) { - sratom_write(sratom, unmap, flags, - subject, &p, prop->type, prop->size, prop->value); - } else { - LILV_WARNF("Lost non-POD property <%s> on save\n", key); - } - } -} - -static int -lilv_state_write(LilvWorld* world, - LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - const LilvState* state, - SerdWriter* writer, - const char* uri, - const char* dir) -{ - SerdNode lv2_appliesTo = serd_node_from_string( - SERD_CURIE, USTR("lv2:appliesTo")); - - const SerdNode* plugin_uri = sord_node_to_serd_node( - state->plugin_uri->node); - - SerdNode subject = serd_node_from_string(SERD_URI, USTR(uri ? uri : "")); - - // a pset:Preset - SerdNode p = serd_node_from_string(SERD_URI, USTR(LILV_NS_RDF "type")); - SerdNode o = serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__Preset)); - serd_writer_write_statement(writer, 0, NULL, - &subject, &p, &o, NULL, NULL); - - // lv2:appliesTo - serd_writer_write_statement(writer, 0, NULL, - &subject, - &lv2_appliesTo, - plugin_uri, NULL, NULL); - - // rdfs:label label - if (state->label) { - p = serd_node_from_string(SERD_URI, USTR(LILV_NS_RDFS "label")); - o = serd_node_from_string(SERD_LITERAL, USTR(state->label)); - serd_writer_write_statement(writer, 0, - NULL, &subject, &p, &o, NULL, NULL); - } - - SerdEnv* env = serd_writer_get_env(writer); - const SerdNode* base = serd_env_get_base_uri(env, NULL); - - Sratom* sratom = sratom_new(map); - sratom_set_sink(sratom, (const char*)base->buf, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, - writer); - - // Write metadata - sratom_set_pretty_numbers(sratom, false); // Use precise types - write_property_array(state, &state->metadata, sratom, 0, - &subject, unmap, dir); - - // Write port values - sratom_set_pretty_numbers(sratom, true); // Use pretty numbers - for (uint32_t i = 0; i < state->n_values; ++i) { - PortValue* const value = &state->values[i]; - - const SerdNode port = serd_node_from_string( - SERD_BLANK, USTR(value->symbol)); - - // <> lv2:port _:symbol - p = serd_node_from_string(SERD_URI, USTR(LV2_CORE__port)); - serd_writer_write_statement(writer, SERD_ANON_O_BEGIN, - NULL, &subject, &p, &port, NULL, NULL); - - // _:symbol lv2:symbol "symbol" - p = serd_node_from_string(SERD_URI, USTR(LV2_CORE__symbol)); - o = serd_node_from_string(SERD_LITERAL, USTR(value->symbol)); - serd_writer_write_statement(writer, SERD_ANON_CONT, - NULL, &port, &p, &o, NULL, NULL); - - // _:symbol pset:value value - p = serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__value)); - sratom_write(sratom, unmap, SERD_ANON_CONT, &port, &p, - value->type, value->size, value->value); - - serd_writer_end_anon(writer, &port); - } - - // Write properties - const SerdNode body = serd_node_from_string(SERD_BLANK, USTR("body")); - if (state->props.n > 0) { - p = serd_node_from_string(SERD_URI, USTR(LV2_STATE__state)); - serd_writer_write_statement(writer, SERD_ANON_O_BEGIN, NULL, - &subject, &p, &body, NULL, NULL); - } - sratom_set_pretty_numbers(sratom, false); // Use precise types - write_property_array(state, &state->props, sratom, SERD_ANON_CONT, - &body, unmap, dir); - - if (state->props.n > 0) { - serd_writer_end_anon(writer, &body); - } - - sratom_free(sratom); - return 0; -} - -static void -lilv_state_make_links(const LilvState* state, const char* dir) -{ - // Create symlinks to files - for (ZixTreeIter* i = zix_tree_begin(state->abs2rel); - i != zix_tree_end(state->abs2rel); - i = zix_tree_iter_next(i)) { - const PathMap* pm = (const PathMap*)zix_tree_get(i); - - char* path = lilv_path_join(dir, pm->rel); - if (lilv_path_is_child(pm->abs, state->copy_dir) - && strcmp(state->copy_dir, dir)) { - // Link directly to snapshot in the copy directory - char* target = lilv_path_relative_to(pm->abs, dir); - lilv_symlink(target, path); - free(target); - } else if (!lilv_path_is_child(pm->abs, dir)) { - const char* link_dir = state->link_dir ? state->link_dir : dir; - char* pat = lilv_path_join(link_dir, pm->rel); - if (!strcmp(dir, link_dir)) { - // Link directory is save directory, make link at exact path - remove(pat); - lilv_symlink(pm->abs, pat); - } else { - // Make a link in the link directory to external file - char* lpath = lilv_find_free_path(pat, link_exists, pm->abs); - if (!lilv_path_exists(lpath, NULL)) { - lilv_symlink(pm->abs, lpath); - } - - // Make a link in the save directory to the external link - char* target = lilv_path_relative_to(lpath, dir); - lilv_symlink(target, path); - free(target); - free(lpath); - } - free(pat); - } - free(path); - } -} - -LILV_API int -lilv_state_save(LilvWorld* world, - LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - const LilvState* state, - const char* uri, - const char* dir, - const char* filename) -{ - if (!filename || !dir || lilv_mkdir_p(dir)) { - return 1; - } - - char* abs_dir = absolute_dir(dir); - char* const path = lilv_path_join(abs_dir, filename); - FILE* fd = fopen(path, "w"); - if (!fd) { - LILV_ERRORF("Failed to open %s (%s)\n", path, strerror(errno)); - free(abs_dir); - free(path); - return 4; - } - - // Create symlinks to files if necessary - lilv_state_make_links(state, abs_dir); - - // Write state to Turtle file - SerdNode file = serd_node_new_file_uri(USTR(path), NULL, NULL, false); - SerdNode node = uri ? serd_node_from_string(SERD_URI, USTR(uri)) : file; - SerdEnv* env = NULL; - SerdWriter* ttl = ttl_file_writer(fd, &file, &env); - int ret = lilv_state_write( - world, map, unmap, state, ttl, (const char*)node.buf, dir); - - // Set saved dir and uri (FIXME: const violation) - SerdNode dir_uri = serd_node_new_file_uri(USTR(abs_dir), NULL, NULL, false); - free(state->dir); - lilv_node_free(state->uri); - ((LilvState*)state)->dir = (char*)dir_uri.buf; - ((LilvState*)state)->uri = lilv_new_uri(world, (const char*)node.buf); - - serd_node_free(&file); - serd_writer_free(ttl); - serd_env_free(env); - fclose(fd); - - // Add entry to manifest - char* const manifest = lilv_path_join(abs_dir, "manifest.ttl"); - add_state_to_manifest(world, state->plugin_uri, manifest, uri, path); - - free(manifest); - free(abs_dir); - free(path); - return ret; -} - -LILV_API char* -lilv_state_to_string(LilvWorld* world, - LV2_URID_Map* map, - LV2_URID_Unmap* unmap, - const LilvState* state, - const char* uri, - const char* base_uri) -{ - if (!uri) { - LILV_ERROR("Attempt to serialise state with no URI\n"); - return NULL; - } - - SerdChunk chunk = { NULL, 0 }; - SerdEnv* env = NULL; - SerdNode base = serd_node_from_string(SERD_URI, USTR(base_uri)); - SerdWriter* writer = ttl_writer(serd_chunk_sink, &chunk, &base, &env); - - lilv_state_write(world, map, unmap, state, writer, uri, NULL); - - serd_writer_free(writer); - serd_env_free(env); - return (char*)serd_chunk_sink_finish(&chunk); -} - -LILV_API int -lilv_state_delete(LilvWorld* world, - const LilvState* state) -{ - if (!state->dir || !state->uri) { - LILV_ERROR("Attempt to delete unsaved state\n"); - return -1; - } - - LilvNode* bundle = lilv_new_uri(world, state->dir); - LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle); - char* manifest_path = lilv_node_get_path(manifest, NULL); - SordModel* model = sord_new(world->world, SORD_SPO, false); - - { - // Read manifest into temporary local model - SerdEnv* env = serd_env_new(sord_node_to_serd_node(manifest->node)); - SerdReader* ttl = sord_new_reader(model, env, SERD_TURTLE, NULL); - serd_reader_read_file(ttl, USTR(manifest_path)); - serd_reader_free(ttl); - serd_env_free(env); - } - - SordNode* file = sord_get( - model, state->uri->node, world->uris.rdfs_seeAlso, NULL, NULL); - if (file) { - // Remove state file - char* path = lilv_file_uri_parse( - (const char*)sord_node_get_string(file), NULL); - if (unlink(path)) { - LILV_ERRORF("Failed to remove %s (%s)\n", path, strerror(errno)); - } - lilv_free(path); - } - - // Remove any existing manifest entries for this state - remove_manifest_entry( - world->world, model, lilv_node_as_string(state->uri)); - remove_manifest_entry( - world->world, world->model, lilv_node_as_string(state->uri)); - - // Drop bundle from model - lilv_world_unload_bundle(world, bundle); - - if (sord_num_quads(model) == 0) { - // Manifest is empty, attempt to remove bundle entirely - if (unlink(manifest_path)) { - LILV_ERRORF("Failed to remove %s (%s)\n", - manifest_path, strerror(errno)); - } - char* dir_path = lilv_file_uri_parse(state->dir, NULL); - if (rmdir(dir_path)) { - LILV_ERRORF("Failed to remove %s (%s)\n", - dir_path, strerror(errno)); - } - lilv_free(dir_path); - } else { - // Still something in the manifest, reload bundle - lilv_world_load_bundle(world, bundle); - } - - sord_free(model); - lilv_free(manifest_path); - lilv_node_free(manifest); - lilv_node_free(bundle); - - return 0; -} - -static void -free_property_array(LilvState* state, PropertyArray* array) -{ - for (uint32_t i = 0; i < array->n; ++i) { - Property* prop = &array->props[i]; - if ((prop->flags & LV2_STATE_IS_POD) || - prop->type == state->atom_Path) { - free(prop->value); - } - } - free(array->props); -} - -LILV_API void -lilv_state_free(LilvState* state) -{ - if (state) { - free_property_array(state, &state->props); - free_property_array(state, &state->metadata); - for (uint32_t i = 0; i < state->n_values; ++i) { - free(state->values[i].value); - free(state->values[i].symbol); - } - lilv_node_free(state->plugin_uri); - lilv_node_free(state->uri); - zix_tree_free(state->abs2rel); - zix_tree_free(state->rel2abs); - free(state->values); - free(state->label); - free(state->dir); - free(state->file_dir); - free(state->copy_dir); - free(state->link_dir); - free(state); - } -} - -LILV_API bool -lilv_state_equals(const LilvState* a, const LilvState* b) -{ - if (!lilv_node_equals(a->plugin_uri, b->plugin_uri) - || (a->label && !b->label) - || (b->label && !a->label) - || (a->label && b->label && strcmp(a->label, b->label)) - || a->props.n != b->props.n - || a->n_values != b->n_values) { - return false; - } - - for (uint32_t i = 0; i < a->n_values; ++i) { - PortValue* const av = &a->values[i]; - PortValue* const bv = &b->values[i]; - if (av->size != bv->size || av->type != bv->type - || strcmp(av->symbol, bv->symbol) - || memcmp(av->value, bv->value, av->size)) { - return false; - } - } - - for (uint32_t i = 0; i < a->props.n; ++i) { - Property* const ap = &a->props.props[i]; - Property* const bp = &b->props.props[i]; - if (ap->key != bp->key - || ap->type != bp->type - || ap->flags != bp->flags) { - return false; - } else if (ap->type == a->atom_Path) { - if (!lilv_file_equals(lilv_state_rel2abs(a, (char*)ap->value), - lilv_state_rel2abs(b, (char*)bp->value))) { - return false; - } - } else if (ap->size != bp->size - || memcmp(ap->value, bp->value, ap->size)) { - return false; - } - } - - return true; -} - -LILV_API unsigned -lilv_state_get_num_properties(const LilvState* state) -{ - return state->props.n; -} - -LILV_API const LilvNode* -lilv_state_get_plugin_uri(const LilvState* state) -{ - return state->plugin_uri; -} - -LILV_API const LilvNode* -lilv_state_get_uri(const LilvState* state) -{ - return state->uri; -} - -LILV_API const char* -lilv_state_get_label(const LilvState* state) -{ - return state->label; -} - -LILV_API void -lilv_state_set_label(LilvState* state, const char* label) -{ - const size_t len = strlen(label); - state->label = (char*)realloc(state->label, len + 1); - memcpy(state->label, label, len + 1); -} - -LILV_API int -lilv_state_set_metadata(LilvState* state, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags) -{ - append_property(state, &state->metadata, key, value, size, type, flags); - return LV2_STATE_SUCCESS; -} diff --git a/source/modules/lilv/lilv-0.24.0/src/util.c.orig b/source/modules/lilv/lilv-0.24.0/src/util.c.orig deleted file mode 100644 index 0c1fd5eb0..000000000 --- a/source/modules/lilv/lilv-0.24.0/src/util.c.orig +++ /dev/null @@ -1,637 +0,0 @@ -/* - Copyright 2007-2016 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. -*/ - -#define _POSIX_C_SOURCE 200809L /* for fileno */ -#define _BSD_SOURCE 1 /* for realpath, symlink */ -#define _DEFAULT_SOURCE 1 /* for realpath, symlink */ - -#ifdef __APPLE__ -# define _DARWIN_C_SOURCE 1 /* for flock */ -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0600 /* for CreateSymbolicLink */ -#endif -# include -# include -# include -# define F_OK 0 -# define mkdir(path, flags) _mkdir(path) -/** Implement 'CreateSymbolicLink()' for MSVC 8 or earlier */ -BOOLEAN WINAPI -CreateSymbolicLink(LPCTSTR linkpath, LPCTSTR targetpath, DWORD flags) -{ - typedef BOOLEAN (WINAPI* PFUNC)(LPCTSTR, LPCTSTR, DWORD); - - PFUNC pfn = (PFUNC)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), - "CreateSymbolicLinkA"); - return pfn ? pfn(linkpath, targetpath, flags) : 0; -} -#else -# include -# include -# include -#endif - -#include -#include - -#include "lilv_internal.h" - -#if defined(HAVE_FLOCK) && defined(HAVE_FILENO) -# include -#endif - -#ifndef PAGE_SIZE -# define PAGE_SIZE 4096 -#endif - -void -lilv_free(void* ptr) -{ - free(ptr); -} - -char* -lilv_strjoin(const char* first, ...) -{ - size_t len = strlen(first); - char* result = (char*)malloc(len + 1); - - memcpy(result, first, len); - - va_list args; - va_start(args, first); - while (1) { - const char* const s = va_arg(args, const char *); - if (s == NULL) - break; - - const size_t this_len = strlen(s); - char* new_result = (char*)realloc(result, len + this_len + 1); - if (!new_result) { - free(result); - return NULL; - } - - result = new_result; - memcpy(result + len, s, this_len); - len += this_len; - } - va_end(args); - - result[len] = '\0'; - - return result; -} - -char* -lilv_strdup(const char* str) -{ - if (!str) { - return NULL; - } - - const size_t len = strlen(str); - char* copy = (char*)malloc(len + 1); - memcpy(copy, str, len + 1); - return copy; -} - -const char* -lilv_uri_to_path(const char* uri) -{ - return (const char*)serd_uri_to_path((const uint8_t*)uri); -} - -char* -lilv_file_uri_parse(const char* uri, char** hostname) -{ - return (char*)serd_file_uri_parse((const uint8_t*)uri, (uint8_t**)hostname); -} - -/** Return the current LANG converted to Turtle (i.e. RFC3066) style. - * For example, if LANG is set to "en_CA.utf-8", this returns "en-ca". - */ -char* -lilv_get_lang(void) -{ - const char* const env_lang = getenv("LANG"); - if (!env_lang || !strcmp(env_lang, "") - || !strcmp(env_lang, "C") || !strcmp(env_lang, "POSIX")) { - return NULL; - } - - const size_t env_lang_len = strlen(env_lang); - char* const lang = (char*)malloc(env_lang_len + 1); - for (size_t i = 0; i < env_lang_len + 1; ++i) { - if (env_lang[i] == '_') { - lang[i] = '-'; // Convert _ to - - } else if (env_lang[i] >= 'A' && env_lang[i] <= 'Z') { - lang[i] = env_lang[i] + ('a' - 'A'); // Convert to lowercase - } else if (env_lang[i] >= 'a' && env_lang[i] <= 'z') { - lang[i] = env_lang[i]; // Lowercase letter, copy verbatim - } else if (env_lang[i] >= '0' && env_lang[i] <= '9') { - lang[i] = env_lang[i]; // Digit, copy verbatim - } else if (env_lang[i] == '\0' || env_lang[i] == '.') { - // End, or start of suffix (e.g. en_CA.utf-8), finished - lang[i] = '\0'; - break; - } else { - LILV_ERRORF("Illegal LANG `%s' ignored\n", env_lang); - free(lang); - return NULL; - } - } - - return lang; -} - -/** Append suffix to dst, update dst_len, and return the realloc'd result. */ -static char* -strappend(char* dst, size_t* dst_len, const char* suffix, size_t suffix_len) -{ - dst = (char*)realloc(dst, *dst_len + suffix_len + 1); - memcpy(dst + *dst_len, suffix, suffix_len); - dst[(*dst_len += suffix_len)] = '\0'; - return dst; -} - -/** Append the value of the environment variable var to dst. */ -static char* -append_var(char* dst, size_t* dst_len, const char* var) -{ - // Get value from environment - const char* val = getenv(var); - if (val) { // Value found, append it - return strappend(dst, dst_len, val, strlen(val)); - } else { // No value found, append variable reference as-is - return strappend(strappend(dst, dst_len, "$", 1), - dst_len, var, strlen(var)); - } -} - -/** Expand variables (e.g. POSIX ~ or $FOO, Windows %FOO%) in `path`. */ -char* -lilv_expand(const char* path) -{ -#ifdef _WIN32 - char* out = (char*)malloc(MAX_PATH); - ExpandEnvironmentStrings(path, out, MAX_PATH); -#else - char* out = NULL; - size_t len = 0; - - const char* start = path; // Start of current chunk to copy - for (const char* s = path; *s;) { - if (*s == '$') { - // Hit $ (variable reference, e.g. $VAR_NAME) - for (const char* t = s + 1; ; ++t) { - if (!*t || (!isupper(*t) && !isdigit(*t) && *t != '_')) { - // Append preceding chunk - out = strappend(out, &len, start, s - start); - - // Append variable value (or $VAR_NAME if not found) - char* var = (char*)calloc(t - s, 1); - memcpy(var, s + 1, t - s - 1); - out = append_var(out, &len, var); - free(var); - - // Continue after variable reference - start = s = t; - break; - } - } - } else if (*s == '~' && (*(s + 1) == '/' || !*(s + 1))) { - // Hit ~ before slash or end of string (home directory reference) - out = strappend(out, &len, start, s - start); - out = append_var(out, &len, "HOME"); - start = ++s; - } else { - ++s; - } - } - - if (*start) { - out = strappend(out, &len, start, strlen(start)); - } -#endif - - return out; -} - -static bool -lilv_is_dir_sep(const char c) -{ - return c == '/' || c == LILV_DIR_SEP[0]; -} - -char* -lilv_dirname(const char* path) -{ - const char* s = path + strlen(path) - 1; // Last character - for (; s > path && lilv_is_dir_sep(*s); --s) {} // Last non-slash - for (; s > path && !lilv_is_dir_sep(*s); --s) {} // Last internal slash - for (; s > path && lilv_is_dir_sep(*s); --s) {} // Skip duplicates - - if (s == path) { // Hit beginning - return lilv_is_dir_sep(*s) ? lilv_strdup("/") : lilv_strdup("."); - } else { // Pointing to the last character of the result (inclusive) - char* dirname = (char*)malloc(s - path + 2); - memcpy(dirname, path, s - path + 1); - dirname[s - path + 1] = '\0'; - return dirname; - } -} - -bool -lilv_path_exists(const char* path, void* ignored) -{ - return !access(path, F_OK); -} - -char* -lilv_find_free_path(const char* in_path, - bool (*exists)(const char*, void*), void* user_data) -{ - const size_t in_path_len = strlen(in_path); - char* path = (char*)malloc(in_path_len + 7); - memcpy(path, in_path, in_path_len + 1); - - for (int i = 2; i < 1000000; ++i) { - if (!exists(path, user_data)) { - return path; - } - snprintf(path, in_path_len + 7, "%s.%u", in_path, i); - } - - return NULL; -} - -int -lilv_copy_file(const char* src, const char* dst) -{ - FILE* in = fopen(src, "r"); - if (!in) { - return errno; - } - - FILE* out = fopen(dst, "w"); - if (!out) { - fclose(in); - return errno; - } - - char* page = (char*)malloc(PAGE_SIZE); - size_t n_read = 0; - int st = 0; - while ((n_read = fread(page, 1, PAGE_SIZE, in)) > 0) { - if (fwrite(page, 1, n_read, out) != n_read) { - st = errno; - break; - } - } - - if (!st && (ferror(in) || ferror(out))) { - st = EBADF; - } - - free(page); - fclose(in); - fclose(out); - - return st; -} - -bool -lilv_path_is_absolute(const char* path) -{ - if (lilv_is_dir_sep(path[0])) { - return true; - } - -#ifdef _WIN32 - if (isalpha(path[0]) && path[1] == ':' && lilv_is_dir_sep(path[2])) { - return true; - } -#endif - - return false; -} - -char* -lilv_path_absolute(const char* path) -{ - if (lilv_path_is_absolute(path)) { - return lilv_strdup(path); - } else { - char* cwd = getcwd(NULL, 0); - char* abs_path = lilv_path_join(cwd, path); - free(cwd); - return abs_path; - } -} - -char* -lilv_path_join(const char* a, const char* b) -{ - if (!a) { - return lilv_strdup(b); - } - - const size_t a_len = strlen(a); - const size_t b_len = b ? strlen(b) : 0; - const size_t pre_len = a_len - (lilv_is_dir_sep(a[a_len - 1]) ? 1 : 0); - char* path = (char*)calloc(1, a_len + b_len + 2); - memcpy(path, a, pre_len); - path[pre_len] = '/'; - if (b) { - memcpy(path + pre_len + 1, - b + (lilv_is_dir_sep(b[0]) ? 1 : 0), - lilv_is_dir_sep(b[0]) ? b_len - 1 : b_len); - } - return path; -} - -typedef struct { - char* pattern; - time_t time; - char* latest; -} Latest; - -static void -update_latest(const char* path, const char* name, void* data) -{ - Latest* latest = (Latest*)data; - char* entry_path = lilv_path_join(path, name); - unsigned num; - if (sscanf(entry_path, latest->pattern, &num) == 1) { - struct stat st; - if (!stat(entry_path, &st)) { - if (st.st_mtime >= latest->time) { - free(latest->latest); - latest->latest = entry_path; - } - } else { - LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno)); - } - } - if (entry_path != latest->latest) { - free(entry_path); - } -} - -/** Return the latest copy of the file at `path` that is newer. */ -char* -lilv_get_latest_copy(const char* path, const char* copy_path) -{ - char* copy_dir = lilv_dirname(copy_path); - Latest latest = { lilv_strjoin(copy_path, ".%u", NULL), 0, NULL }; - - struct stat st; - if (!stat(path, &st)) { - latest.time = st.st_mtime; - } else { - LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno)); - } - - lilv_dir_for_each(copy_dir, &latest, update_latest); - - free(latest.pattern); - free(copy_dir); - return latest.latest; -} - -char* -lilv_realpath(const char* path) -{ -#if defined(_WIN32) - char* out = (char*)malloc(MAX_PATH); - GetFullPathName(path, MAX_PATH, out, NULL); - return out; -#elif _POSIX_VERSION >= 200809L - char* real_path = realpath(path, NULL); - return real_path ? real_path : lilv_strdup(path); -#else - // OSX <= 10.5, if anyone cares. I sure don't. - char* out = (char*)malloc(PATH_MAX); - char* real_path = realpath(path, out); - if (!real_path) { - free(out); - return lilv_strdup(path); - } else { - return real_path; - } -#endif -} - -int -lilv_symlink(const char* oldpath, const char* newpath) -{ - int ret = 0; - if (strcmp(oldpath, newpath)) { -#ifdef _WIN32 - ret = !CreateSymbolicLink(newpath, oldpath, 0); - if (ret) { - ret = !CreateHardLink(newpath, oldpath, 0); - } -#else - ret = symlink(oldpath, newpath); -#endif - } - if (ret) { - LILV_ERRORF("Failed to link %s => %s (%s)\n", - newpath, oldpath, strerror(errno)); - } - return ret; -} - -char* -lilv_path_relative_to(const char* path, const char* base) -{ - const size_t path_len = strlen(path); - const size_t base_len = strlen(base); - const size_t min_len = (path_len < base_len) ? path_len : base_len; - - // Find the last separator common to both paths - size_t last_shared_sep = 0; - for (size_t i = 0; i < min_len && path[i] == base[i]; ++i) { - if (lilv_is_dir_sep(path[i])) { - last_shared_sep = i; - } - } - - if (last_shared_sep == 0) { - // No common components, return path - return lilv_strdup(path); - } - - // Find the number of up references ("..") required - size_t up = 0; - for (size_t i = last_shared_sep + 1; i < base_len; ++i) { - if (lilv_is_dir_sep(base[i])) { - ++up; - } - } - - // Write up references - const size_t suffix_len = path_len - last_shared_sep; - char* rel = (char*)calloc(1, suffix_len + (up * 3) + 1); - for (size_t i = 0; i < up; ++i) { - memcpy(rel + (i * 3), "../", 3); - } - - // Write suffix - memcpy(rel + (up * 3), path + last_shared_sep + 1, suffix_len); - return rel; -} - -bool -lilv_path_is_child(const char* path, const char* dir) -{ - if (path && dir) { - const size_t path_len = strlen(path); - const size_t dir_len = strlen(dir); - return dir && path_len >= dir_len && !strncmp(path, dir, dir_len); - } - return false; -} - -int -lilv_flock(FILE* file, bool lock) -{ -#if defined(HAVE_FLOCK) && defined(HAVE_FILENO) - return flock(fileno(file), lock ? LOCK_EX : LOCK_UN); -#else - return 0; -#endif -} - -void -lilv_dir_for_each(const char* path, - void* data, - void (*f)(const char* path, const char* name, void* data)) -{ -#ifdef _WIN32 - char* pat = lilv_path_join(path, "*"); - WIN32_FIND_DATA fd; - HANDLE fh = FindFirstFile(pat, &fd); - if (fh != INVALID_HANDLE_VALUE) { - do { - f(path, fd.cFileName, data); - } while (FindNextFile(fh, &fd)); - } - free(pat); -#else - DIR* dir = opendir(path); - if (dir) { - long name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { - name_max = 255; // Limit not defined, or error - } - - const size_t len = offsetof(struct dirent, d_name) + name_max + 1; - struct dirent* entry = (struct dirent*)malloc(len); - struct dirent* result; - while (!readdir_r(dir, entry, &result) && result) { - f(path, entry->d_name, data); - } - free(entry); - closedir(dir); - } -#endif -} - -int -lilv_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) { - free(path); - return errno; - } - path[i] = LILV_DIR_SEP[0]; - } - } - - free(path); - return 0; -} - -static off_t -lilv_file_size(const char* path) -{ - struct stat buf; - if (stat(path, &buf)) { - LILV_ERRORF("stat(%s) (%s)\n", path, strerror(errno)); - return 0; - } - return buf.st_size; -} - -bool -lilv_file_equals(const char* a_path, const char* b_path) -{ - if (!strcmp(a_path, b_path)) { - return true; // Paths match - } - - bool match = false; - FILE* a_file = NULL; - FILE* b_file = NULL; - char* const a_real = lilv_realpath(a_path); - char* const b_real = lilv_realpath(b_path); - if (!strcmp(a_real, b_real)) { - match = true; // Real paths match - } else if (lilv_file_size(a_path) != lilv_file_size(b_path)) { - match = false; // Sizes differ - } else if (!(a_file = fopen(a_real, "rb")) || - !(b_file = fopen(b_real, "rb"))) { - match = false; // Missing file matches nothing - } else { - // TODO: Improve performance by reading chunks - match = true; - while (!feof(a_file) && !feof(b_file)) { - if (fgetc(a_file) != fgetc(b_file)) { - match = false; - break; - } - } - } - - if (a_file) { - fclose(a_file); - } - if (b_file) { - fclose(b_file); - } - free(a_real); - free(b_real); - return match; -} diff --git a/source/modules/lilv/lilv-0.24.0/src/world.c.orig b/source/modules/lilv/lilv-0.24.0/src/world.c.orig deleted file mode 100644 index 04403ca95..000000000 --- a/source/modules/lilv/lilv-0.24.0/src/world.c.orig +++ /dev/null @@ -1,1194 +0,0 @@ -/* - Copyright 2007-2016 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 "lv2/presets.h" - -#include "lilv_internal.h" - -static int -lilv_world_drop_graph(LilvWorld* world, const SordNode* graph); - -LILV_API LilvWorld* -lilv_world_new(void) -{ - LilvWorld* world = (LilvWorld*)malloc(sizeof(LilvWorld)); - - world->world = sord_world_new(); - if (!world->world) - goto fail; - - world->model = sord_new(world->world, SORD_SPO|SORD_OPS, true); - if (!world->model) - goto fail; - - world->specs = NULL; - world->plugin_classes = lilv_plugin_classes_new(); - world->plugins = lilv_plugins_new(); - world->zombies = lilv_plugins_new(); - world->loaded_files = zix_tree_new( - false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free); - - world->libs = zix_tree_new(false, lilv_lib_compare, NULL, NULL); - -#define NS_DCTERMS "http://purl.org/dc/terms/" -#define NS_DYNMAN "http://lv2plug.in/ns/ext/dynmanifest#" -#define NS_OWL "http://www.w3.org/2002/07/owl#" - -#define NEW_URI(uri) sord_new_uri(world->world, (const uint8_t*)uri) - - world->uris.dc_replaces = NEW_URI(NS_DCTERMS "replaces"); - world->uris.dman_DynManifest = NEW_URI(NS_DYNMAN "DynManifest"); - world->uris.doap_name = NEW_URI(LILV_NS_DOAP "name"); - world->uris.lv2_Plugin = NEW_URI(LV2_CORE__Plugin); - world->uris.lv2_Specification = NEW_URI(LV2_CORE__Specification); - world->uris.lv2_appliesTo = NEW_URI(LV2_CORE__appliesTo); - world->uris.lv2_binary = NEW_URI(LV2_CORE__binary); - world->uris.lv2_default = NEW_URI(LV2_CORE__default); - world->uris.lv2_designation = NEW_URI(LV2_CORE__designation); - world->uris.lv2_extensionData = NEW_URI(LV2_CORE__extensionData); - world->uris.lv2_index = NEW_URI(LV2_CORE__index); - world->uris.lv2_latency = NEW_URI(LV2_CORE__latency); - world->uris.lv2_maximum = NEW_URI(LV2_CORE__maximum); - world->uris.lv2_microVersion = NEW_URI(LV2_CORE__microVersion); - world->uris.lv2_minimum = NEW_URI(LV2_CORE__minimum); - world->uris.lv2_minorVersion = NEW_URI(LV2_CORE__minorVersion); - world->uris.lv2_name = NEW_URI(LV2_CORE__name); - world->uris.lv2_optionalFeature = NEW_URI(LV2_CORE__optionalFeature); - world->uris.lv2_port = NEW_URI(LV2_CORE__port); - world->uris.lv2_portProperty = NEW_URI(LV2_CORE__portProperty); - world->uris.lv2_reportsLatency = NEW_URI(LV2_CORE__reportsLatency); - world->uris.lv2_requiredFeature = NEW_URI(LV2_CORE__requiredFeature); - world->uris.lv2_symbol = NEW_URI(LV2_CORE__symbol); - world->uris.lv2_prototype = NEW_URI(LV2_CORE__prototype); - world->uris.owl_Ontology = NEW_URI(NS_OWL "Ontology"); - world->uris.pset_value = NEW_URI(LV2_PRESETS__value); - world->uris.rdf_a = NEW_URI(LILV_NS_RDF "type"); - world->uris.rdf_value = NEW_URI(LILV_NS_RDF "value"); - world->uris.rdfs_Class = NEW_URI(LILV_NS_RDFS "Class"); - world->uris.rdfs_label = NEW_URI(LILV_NS_RDFS "label"); - world->uris.rdfs_seeAlso = NEW_URI(LILV_NS_RDFS "seeAlso"); - world->uris.rdfs_subClassOf = NEW_URI(LILV_NS_RDFS "subClassOf"); - world->uris.xsd_base64Binary = NEW_URI(LILV_NS_XSD "base64Binary"); - world->uris.xsd_boolean = NEW_URI(LILV_NS_XSD "boolean"); - world->uris.xsd_decimal = NEW_URI(LILV_NS_XSD "decimal"); - world->uris.xsd_double = NEW_URI(LILV_NS_XSD "double"); - world->uris.xsd_integer = NEW_URI(LILV_NS_XSD "integer"); - world->uris.null_uri = NULL; - - world->lv2_plugin_class = lilv_plugin_class_new( - world, NULL, world->uris.lv2_Plugin, "Plugin"); - assert(world->lv2_plugin_class); - - world->n_read_files = 0; - world->opt.filter_language = true; - world->opt.dyn_manifest = true; - - return world; - -fail: - /* keep on rockin' in the */ free(world); - return NULL; -} - -LILV_API void -lilv_world_free(LilvWorld* world) -{ - if (!world) { - return; - } - - lilv_plugin_class_free(world->lv2_plugin_class); - world->lv2_plugin_class = NULL; - - for (SordNode** n = (SordNode**)&world->uris; *n; ++n) { - sord_node_free(world->world, *n); - } - - for (LilvSpec* spec = world->specs; spec;) { - LilvSpec* next = spec->next; - sord_node_free(world->world, spec->spec); - sord_node_free(world->world, spec->bundle); - lilv_nodes_free(spec->data_uris); - free(spec); - spec = next; - } - world->specs = NULL; - - LILV_FOREACH(plugins, i, world->plugins) { - const LilvPlugin* p = lilv_plugins_get(world->plugins, i); - lilv_plugin_free((LilvPlugin*)p); - } - zix_tree_free((ZixTree*)world->plugins); - world->plugins = NULL; - - LILV_FOREACH(plugins, i, world->zombies) { - const LilvPlugin* p = lilv_plugins_get(world->zombies, i); - lilv_plugin_free((LilvPlugin*)p); - } - zix_tree_free((ZixTree*)world->zombies); - world->zombies = NULL; - - zix_tree_free((ZixTree*)world->loaded_files); - world->loaded_files = NULL; - - zix_tree_free((ZixTree*)world->libs); - world->libs = NULL; - - zix_tree_free((ZixTree*)world->plugin_classes); - world->plugin_classes = NULL; - - sord_free(world->model); - world->model = NULL; - - sord_world_free(world->world); - world->world = NULL; - - free(world); -} - -LILV_API void -lilv_world_set_option(LilvWorld* world, - const char* option, - const LilvNode* value) -{ - if (!strcmp(option, LILV_OPTION_DYN_MANIFEST)) { - if (lilv_node_is_bool(value)) { - world->opt.dyn_manifest = lilv_node_as_bool(value); - return; - } - } else if (!strcmp(option, LILV_OPTION_FILTER_LANG)) { - if (lilv_node_is_bool(value)) { - world->opt.filter_language = lilv_node_as_bool(value); - return; - } - } - LILV_WARNF("Unrecognized or invalid option `%s'\n", option); -} - -LILV_API LilvNodes* -lilv_world_find_nodes(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object) -{ - if (subject && !lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) { - LILV_ERRORF("Subject `%s' is not a resource\n", - sord_node_get_string(subject->node)); - return NULL; - } else if (!predicate) { - LILV_ERROR("Missing required predicate\n"); - return NULL; - } else if (!lilv_node_is_uri(predicate)) { - LILV_ERRORF("Predicate `%s' is not a URI\n", - sord_node_get_string(predicate->node)); - return NULL; - } else if (!subject && !object) { - LILV_ERROR("Both subject and object are NULL\n"); - return NULL; - } - - return lilv_world_find_nodes_internal(world, - subject ? subject->node : NULL, - predicate->node, - object ? object->node : NULL); -} - -LILV_API LilvNode* -lilv_world_get(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object) -{ - SordNode* snode = sord_get(world->model, - subject ? subject->node : NULL, - predicate ? predicate->node : NULL, - object ? object->node : NULL, - NULL); - LilvNode* lnode = lilv_node_new_from_node(world, snode); - sord_node_free(world->world, snode); - return lnode; -} - -SordIter* -lilv_world_query_internal(LilvWorld* world, - const SordNode* subject, - const SordNode* predicate, - const SordNode* object) -{ - return sord_search(world->model, subject, predicate, object, NULL); -} - -bool -lilv_world_ask_internal(LilvWorld* world, - const SordNode* subject, - const SordNode* predicate, - const SordNode* object) -{ - return sord_ask(world->model, subject, predicate, object, NULL); -} - -LILV_API bool -lilv_world_ask(LilvWorld* world, - const LilvNode* subject, - const LilvNode* predicate, - const LilvNode* object) -{ - return sord_ask(world->model, - subject ? subject->node : NULL, - predicate ? predicate->node : NULL, - object ? object->node : NULL, - NULL); -} - -SordModel* -lilv_world_filter_model(LilvWorld* world, - SordModel* model, - const SordNode* subject, - const SordNode* predicate, - const SordNode* object, - const SordNode* graph) -{ - SordModel* results = sord_new(world->world, SORD_SPO, false); - SordIter* i = sord_search(model, subject, predicate, object, graph); - for (; !sord_iter_end(i); sord_iter_next(i)) { - SordQuad quad; - sord_iter_get(i, quad); - sord_add(results, quad); - } - sord_iter_free(i); - return results; -} - -LilvNodes* -lilv_world_find_nodes_internal(LilvWorld* world, - const SordNode* subject, - const SordNode* predicate, - const SordNode* object) -{ - return lilv_nodes_from_stream_objects( - world, - lilv_world_query_internal(world, subject, predicate, object), - (object == NULL) ? SORD_OBJECT : SORD_SUBJECT); -} - -static SerdNode -lilv_new_uri_relative_to_base(const uint8_t* uri_str, - const uint8_t* base_uri_str) -{ - SerdURI base_uri; - serd_uri_parse(base_uri_str, &base_uri); - return serd_node_new_uri_from_string(uri_str, &base_uri, NULL); -} - -const uint8_t* -lilv_world_blank_node_prefix(LilvWorld* world) -{ - static char str[32]; - snprintf(str, sizeof(str), "%d", world->n_read_files++); - return (const uint8_t*)str; -} - -/** Comparator for sequences (e.g. world->plugins). */ -int -lilv_header_compare_by_uri(const void* a, const void* b, void* user_data) -{ - const struct LilvHeader* const header_a = (const struct LilvHeader*)a; - const struct LilvHeader* const header_b = (const struct LilvHeader*)b; - return strcmp(lilv_node_as_uri(header_a->uri), - lilv_node_as_uri(header_b->uri)); -} - -/** - Comparator for libraries (world->libs). - - Libraries do have a LilvHeader, but we must also compare the bundle to - handle the case where the same library is loaded with different bundles, and - consequently different contents (mainly plugins). - */ -int -lilv_lib_compare(const void* a, const void* b, void* user_data) -{ - const LilvLib* const lib_a = (const LilvLib*)a; - const LilvLib* const lib_b = (const LilvLib*)b; - int cmp = strcmp(lilv_node_as_uri(lib_a->uri), - lilv_node_as_uri(lib_b->uri)); - return cmp ? cmp : strcmp(lib_a->bundle_path, lib_b->bundle_path); -} - -/** Get an element of a collection of any object with an LilvHeader by URI. */ -static ZixTreeIter* -lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri) -{ - ZixTreeIter* i = NULL; - if (lilv_node_is_uri(uri)) { - struct LilvHeader key = { NULL, (LilvNode*)uri }; - zix_tree_find(seq, &key, &i); - } - return i; -} - -/** Get an element of a collection of any object with an LilvHeader by URI. */ -struct LilvHeader* -lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri) -{ - ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri); - - return i ? (struct LilvHeader*)zix_tree_get(i) : NULL; -} - -static void -lilv_world_add_spec(LilvWorld* world, - const SordNode* specification_node, - const SordNode* bundle_node) -{ - LilvSpec* spec = (LilvSpec*)malloc(sizeof(LilvSpec)); - spec->spec = sord_node_copy(specification_node); - spec->bundle = sord_node_copy(bundle_node); - spec->data_uris = lilv_nodes_new(); - - // Add all data files (rdfs:seeAlso) - SordIter* files = sord_search(world->model, - specification_node, - world->uris.rdfs_seeAlso, - NULL, - NULL); - FOREACH_MATCH(files) { - const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); - zix_tree_insert((ZixTree*)spec->data_uris, - lilv_node_new_from_node(world, file_node), - NULL); - } - sord_iter_free(files); - - // Add specification to world specification list - spec->next = world->specs; - world->specs = spec; -} - -static void -lilv_world_add_plugin(LilvWorld* world, - const SordNode* plugin_node, - const LilvNode* manifest_uri, - void* dynmanifest, - const SordNode* bundle) -{ - LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node); - ZixTreeIter* z = NULL; - LilvPlugin* plugin = (LilvPlugin*)lilv_plugins_get_by_uri( - world->plugins, plugin_uri); - - if (plugin) { - // Existing plugin, if this is different bundle, ignore it - // (use the first plugin found in LV2_PATH) - const LilvNode* last_bundle = lilv_plugin_get_bundle_uri(plugin); - const char* plugin_uri_str = lilv_node_as_uri(plugin_uri); - if (sord_node_equals(bundle, last_bundle->node)) { - LILV_WARNF("Reloading plugin <%s>\n", plugin_uri_str); - plugin->loaded = false; - lilv_node_free(plugin_uri); - } else { - LILV_WARNF("Duplicate plugin <%s>\n", plugin_uri_str); - LILV_WARNF("... found in %s\n", lilv_node_as_string(last_bundle)); - LILV_WARNF("... and %s (ignored)\n", sord_node_get_string(bundle)); - lilv_node_free(plugin_uri); - return; - } - } else if ((z = lilv_collection_find_by_uri((const ZixTree*)world->zombies, - plugin_uri))) { - // Plugin bundle has been re-loaded, move from zombies to plugins - plugin = (LilvPlugin*)zix_tree_get(z); - zix_tree_remove((ZixTree*)world->zombies, z); - zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); - lilv_node_free(plugin_uri); - lilv_plugin_clear(plugin, lilv_node_new_from_node(world, bundle)); - } else { - // Add new plugin to the world - plugin = lilv_plugin_new( - world, plugin_uri, lilv_node_new_from_node(world, bundle)); - - // Add manifest as plugin data file (as if it were rdfs:seeAlso) - zix_tree_insert((ZixTree*)plugin->data_uris, - lilv_node_duplicate(manifest_uri), - NULL); - - // Add plugin to world plugin sequence - zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); - } - - -#ifdef LILV_DYN_MANIFEST - // Set dynamic manifest library URI, if applicable - if (dynmanifest) { - plugin->dynmanifest = (LilvDynManifest*)dynmanifest; - ++((LilvDynManifest*)dynmanifest)->refs; - } -#endif - - // Add all plugin data files (rdfs:seeAlso) - SordIter* files = sord_search(world->model, - plugin_node, - world->uris.rdfs_seeAlso, - NULL, - NULL); - FOREACH_MATCH(files) { - const SordNode* file_node = sord_iter_get_node(files, SORD_OBJECT); - zix_tree_insert((ZixTree*)plugin->data_uris, - lilv_node_new_from_node(world, file_node), - NULL); - } - sord_iter_free(files); -} - -SerdStatus -lilv_world_load_graph(LilvWorld* world, SordNode* graph, const LilvNode* uri) -{ - const SerdNode* base = sord_node_to_serd_node(uri->node); - SerdEnv* env = serd_env_new(base); - SerdReader* reader = sord_new_reader( - world->model, env, SERD_TURTLE, graph); - - const SerdStatus st = lilv_world_load_file(world, reader, uri); - - serd_env_free(env); - serd_reader_free(reader); - return st; -} - -static void -lilv_world_load_dyn_manifest(LilvWorld* world, - SordNode* bundle_node, - const LilvNode* manifest) -{ -#ifdef LILV_DYN_MANIFEST - if (!world->opt.dyn_manifest) { - return; - } - - typedef void* LV2_Dyn_Manifest_Handle; - LV2_Dyn_Manifest_Handle handle = NULL; - - // ?dman a dynman:DynManifest bundle_node - SordModel* model = lilv_world_filter_model(world, - world->model, - NULL, - world->uris.rdf_a, - world->uris.dman_DynManifest, - bundle_node); - SordIter* iter = sord_begin(model); - for (; !sord_iter_end(iter); sord_iter_next(iter)) { - const SordNode* dmanifest = sord_iter_get_node(iter, SORD_SUBJECT); - - // ?dman lv2:binary ?binary - SordIter* binaries = sord_search(world->model, - dmanifest, - world->uris.lv2_binary, - NULL, - bundle_node); - if (sord_iter_end(binaries)) { - sord_iter_free(binaries); - LILV_ERRORF("Dynamic manifest in <%s> has no binaries, ignored\n", - sord_node_get_string(bundle_node)); - continue; - } - - // Get binary path - const SordNode* binary = sord_iter_get_node(binaries, SORD_OBJECT); - const uint8_t* lib_uri = sord_node_get_string(binary); - char* lib_path = lilv_file_uri_parse((const char*)lib_uri, 0); - if (!lib_path) { - LILV_ERROR("No dynamic manifest library path\n"); - sord_iter_free(binaries); - continue; - } - - // Open library - dlerror(); - void* lib = dlopen(lib_path, RTLD_LAZY); - if (!lib) { - LILV_ERRORF("Failed to open dynmanifest library `%s' (%s)\n", - lib_path, dlerror()); - sord_iter_free(binaries); - lilv_free(lib_path); - continue; - } - - // Open dynamic manifest - typedef int (*OpenFunc)(LV2_Dyn_Manifest_Handle*, - const LV2_Feature *const *); - OpenFunc dmopen = (OpenFunc)lilv_dlfunc(lib, "lv2_dyn_manifest_open"); - if (!dmopen || dmopen(&handle, &dman_features)) { - LILV_ERRORF("No `lv2_dyn_manifest_open' in `%s'\n", lib_path); - sord_iter_free(binaries); - dlclose(lib); - lilv_free(lib_path); - continue; - } - - // Get subjects (the data that would be in manifest.ttl) - typedef int (*GetSubjectsFunc)(LV2_Dyn_Manifest_Handle, FILE*); - GetSubjectsFunc get_subjects_func = (GetSubjectsFunc)lilv_dlfunc( - lib, "lv2_dyn_manifest_get_subjects"); - if (!get_subjects_func) { - LILV_ERRORF("No `lv2_dyn_manifest_get_subjects' in `%s'\n", - lib_path); - sord_iter_free(binaries); - dlclose(lib); - lilv_free(lib_path); - continue; - } - - LilvDynManifest* desc = malloc(sizeof(LilvDynManifest)); - desc->bundle = lilv_node_new_from_node(world, bundle_node); - desc->lib = lib; - desc->handle = handle; - desc->refs = 0; - - sord_iter_free(binaries); - - // Generate data file - FILE* fd = tmpfile(); - get_subjects_func(handle, fd); - rewind(fd); - - // Parse generated data file into temporary model - // FIXME - const SerdNode* base = sord_node_to_serd_node(dmanifest); - SerdEnv* env = serd_env_new(base); - SerdReader* reader = sord_new_reader( - world->model, env, SERD_TURTLE, sord_node_copy(dmanifest)); - serd_reader_add_blank_prefix(reader, - lilv_world_blank_node_prefix(world)); - serd_reader_read_file_handle(reader, fd, - (const uint8_t*)"(dyn-manifest)"); - serd_reader_free(reader); - serd_env_free(env); - - // Close (and automatically delete) temporary data file - fclose(fd); - - // ?plugin a lv2:Plugin - SordModel* plugins = lilv_world_filter_model(world, - world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - dmanifest); - SordIter* p = sord_begin(plugins); - FOREACH_MATCH(p) { - const SordNode* plug = sord_iter_get_node(p, SORD_SUBJECT); - lilv_world_add_plugin(world, plug, manifest, desc, bundle_node); - } - sord_iter_free(p); - sord_free(plugins); - lilv_free(lib_path); - } - sord_iter_free(iter); - sord_free(model); -#endif // LILV_DYN_MANIFEST -} - -LilvNode* -lilv_world_get_manifest_uri(LilvWorld* world, const LilvNode* bundle_uri) -{ - SerdNode manifest_uri = lilv_new_uri_relative_to_base( - (const uint8_t*)"manifest.ttl", - (const uint8_t*)sord_node_get_string(bundle_uri->node)); - LilvNode* manifest = lilv_new_uri(world, (const char*)manifest_uri.buf); - serd_node_free(&manifest_uri); - return manifest; -} - -static SordModel* -load_plugin_model(LilvWorld* world, - const LilvNode* bundle_uri, - const LilvNode* plugin_uri) -{ - // Create model and reader for loading into it - SordNode* bundle_node = bundle_uri->node; - SordModel* model = sord_new(world->world, SORD_SPO|SORD_OPS, false); - SerdEnv* env = serd_env_new(sord_node_to_serd_node(bundle_node)); - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - - // Load manifest - LilvNode* manifest_uri = lilv_world_get_manifest_uri(world, bundle_uri); - serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); - serd_reader_read_file( - reader, (const uint8_t*)lilv_node_as_string(manifest_uri)); - - // Load any seeAlso files - SordModel* files = lilv_world_filter_model( - world, model, plugin_uri->node, world->uris.rdfs_seeAlso, NULL, NULL); - - SordIter* f = sord_begin(files); - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - const uint8_t* file_str = sord_node_get_string(file); - if (sord_node_get_type(file) == SORD_URI) { - serd_reader_add_blank_prefix( - reader, lilv_world_blank_node_prefix(world)); - serd_reader_read_file(reader, file_str); - } - } - - sord_iter_free(f); - sord_free(files); - serd_reader_free(reader); - serd_env_free(env); - lilv_node_free(manifest_uri); - - return model; -} - -static LilvVersion -get_version(LilvWorld* world, SordModel* model, const LilvNode* subject) -{ - const SordNode* minor_node = sord_get( - model, subject->node, world->uris.lv2_minorVersion, NULL, NULL); - const SordNode* micro_node = sord_get( - model, subject->node, world->uris.lv2_microVersion, NULL, NULL); - - - LilvVersion version = { 0, 0 }; - if (minor_node && micro_node) { - version.minor = atoi((const char*)sord_node_get_string(minor_node)); - version.micro = atoi((const char*)sord_node_get_string(micro_node)); - } - - return version; -} - -LILV_API void -lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri) -{ - if (!lilv_node_is_uri(bundle_uri)) { - LILV_ERRORF("Bundle URI `%s' is not a URI\n", - sord_node_get_string(bundle_uri->node)); - return; - } - - SordNode* bundle_node = bundle_uri->node; - LilvNode* manifest = lilv_world_get_manifest_uri(world, bundle_uri); - - // Read manifest into model with graph = bundle_node - SerdStatus st = lilv_world_load_graph(world, bundle_node, manifest); - if (st > SERD_FAILURE) { - LILV_ERRORF("Error reading %s\n", lilv_node_as_string(manifest)); - lilv_node_free(manifest); - return; - } - - // ?plugin a lv2:Plugin - SordIter* plug_results = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - bundle_node); - - // Find any loaded plugins that will be replaced with a newer version - LilvNodes* unload_uris = lilv_nodes_new(); - FOREACH_MATCH(plug_results) { - const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); - - LilvNode* plugin_uri = lilv_node_new_from_node(world, plug); - const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, plugin_uri); - const LilvNode* last_bundle = plugin ? lilv_plugin_get_bundle_uri(plugin) : NULL; - if (!plugin || sord_node_equals(bundle_node, last_bundle->node)) { - // No previously loaded version, or it's from the same bundle - lilv_node_free(plugin_uri); - continue; - } - - // Compare versions - SordModel* this_model = load_plugin_model(world, bundle_uri, plugin_uri); - LilvVersion this_version = get_version(world, this_model, plugin_uri); - SordModel* last_model = load_plugin_model(world, last_bundle, plugin_uri); - LilvVersion last_version = get_version(world, last_model, plugin_uri); - sord_free(this_model); - sord_free(last_model); - const int cmp = lilv_version_cmp(&this_version, &last_version); - if (cmp > 0) { - zix_tree_insert((ZixTree*)unload_uris, - lilv_node_duplicate(plugin_uri), - NULL); - LILV_WARNF("Replacing version %d.%d of <%s> from <%s>\n", - last_version.minor, last_version.micro, - sord_node_get_string(plug), - sord_node_get_string(last_bundle->node)); - LILV_NOTEF("New version %d.%d found in <%s>\n", - this_version.minor, this_version.micro, - sord_node_get_string(bundle_node)); - } else if (cmp < 0) { - LILV_WARNF("Ignoring bundle <%s>\n", - sord_node_get_string(bundle_node)); - LILV_NOTEF("Newer version of <%s> loaded from <%s>\n", - sord_node_get_string(plug), - sord_node_get_string(last_bundle->node)); - lilv_node_free(plugin_uri); - sord_iter_free(plug_results); - lilv_world_drop_graph(world, bundle_node); - lilv_node_free(manifest); - lilv_nodes_free(unload_uris); - return; - } - lilv_node_free(plugin_uri); - } - - sord_iter_free(plug_results); - - // Unload any old conflicting plugins - LilvNodes* unload_bundles = lilv_nodes_new(); - LILV_FOREACH(nodes, i, unload_uris) { - const LilvNode* uri = lilv_nodes_get(unload_uris, i); - const LilvPlugin* plugin = lilv_plugins_get_by_uri(world->plugins, uri); - const LilvNode* bundle = lilv_plugin_get_bundle_uri(plugin); - - // Unload plugin and record bundle for later unloading - lilv_world_unload_resource(world, uri); - zix_tree_insert((ZixTree*)unload_bundles, - lilv_node_duplicate(bundle), - NULL); - - } - lilv_nodes_free(unload_uris); - - // Now unload the associated bundles - // This must be done last since several plugins could be in the same bundle - LILV_FOREACH(nodes, i, unload_bundles) { - lilv_world_unload_bundle(world, lilv_nodes_get(unload_bundles, i)); - } - lilv_nodes_free(unload_bundles); - - // Re-search for plugin results now that old plugins are gone - plug_results = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.lv2_Plugin, - bundle_node); - - FOREACH_MATCH(plug_results) { - const SordNode* plug = sord_iter_get_node(plug_results, SORD_SUBJECT); - lilv_world_add_plugin(world, plug, manifest, NULL, bundle_node); - } - sord_iter_free(plug_results); - - lilv_world_load_dyn_manifest(world, bundle_node, manifest); - - // ?spec a lv2:Specification - // ?spec a owl:Ontology - const SordNode* spec_preds[] = { world->uris.lv2_Specification, - world->uris.owl_Ontology, - NULL }; - for (const SordNode** p = spec_preds; *p; ++p) { - SordIter* i = sord_search( - world->model, NULL, world->uris.rdf_a, *p, bundle_node); - FOREACH_MATCH(i) { - const SordNode* spec = sord_iter_get_node(i, SORD_SUBJECT); - lilv_world_add_spec(world, spec, bundle_node); - } - sord_iter_free(i); - } - - lilv_node_free(manifest); -} - -static int -lilv_world_drop_graph(LilvWorld* world, const SordNode* graph) -{ - SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph); - while (!sord_iter_end(i)) { - const SerdStatus st = sord_erase(world->model, i); - if (st) { - LILV_ERRORF("Error removing statement from <%s> (%s)\n", - sord_node_get_string(graph), serd_strerror(st)); - return st; - } - } - sord_iter_free(i); - - return 0; -} - -/** Remove loaded_files entry so file will be reloaded if requested. */ -static int -lilv_world_unload_file(LilvWorld* world, const LilvNode* file) -{ - ZixTreeIter* iter; - if (!zix_tree_find((ZixTree*)world->loaded_files, file, &iter)) { - zix_tree_remove((ZixTree*)world->loaded_files, iter); - return 0; - } - return 1; -} - -LILV_API int -lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri) -{ - if (!bundle_uri) { - return 0; - } - - // Find all loaded files that are inside the bundle - LilvNodes* files = lilv_nodes_new(); - LILV_FOREACH(nodes, i, world->loaded_files) { - const LilvNode* file = lilv_nodes_get(world->loaded_files, i); - if (!strncmp(lilv_node_as_string(file), - lilv_node_as_string(bundle_uri), - strlen(lilv_node_as_string(bundle_uri)))) { - zix_tree_insert((ZixTree*)files, - lilv_node_duplicate(file), - NULL); - } - } - - // Unload all loaded files in the bundle - LILV_FOREACH(nodes, i, files) { - const LilvNode* file = lilv_nodes_get(world->plugins, i); - lilv_world_unload_file(world, file); - } - - lilv_nodes_free(files); - - /* Remove any plugins in the bundle from the plugin list. Since the - application may still have a pointer to the LilvPlugin, it can not be - destroyed here. Instead, we move it to the zombie plugin list, so it - will not be in the list returned by lilv_world_get_all_plugins() but can - still be used. - */ - ZixTreeIter* i = zix_tree_begin((ZixTree*)world->plugins); - while (i != zix_tree_end((ZixTree*)world->plugins)) { - LilvPlugin* p = (LilvPlugin*)zix_tree_get(i); - ZixTreeIter* next = zix_tree_iter_next(i); - - if (lilv_node_equals(lilv_plugin_get_bundle_uri(p), bundle_uri)) { - zix_tree_remove((ZixTree*)world->plugins, i); - zix_tree_insert((ZixTree*)world->zombies, p, NULL); - } - - i = next; - } - - // Drop everything in bundle graph - return lilv_world_drop_graph(world, bundle_uri->node); -} - -static void -load_dir_entry(const char* dir, const char* name, void* data) -{ - LilvWorld* world = (LilvWorld*)data; - if (!strcmp(name, ".") || !strcmp(name, "..")) - return; - - char* path = lilv_strjoin(dir, "/", name, "/", NULL); - SerdNode suri = serd_node_new_file_uri((const uint8_t*)path, 0, 0, true); - LilvNode* node = lilv_new_uri(world, (const char*)suri.buf); - - lilv_world_load_bundle(world, node); - lilv_node_free(node); - serd_node_free(&suri); - free(path); -} - -/** Load all bundles in the directory at `dir_path`. */ -static void -lilv_world_load_directory(LilvWorld* world, const char* dir_path) -{ - char* path = lilv_expand(dir_path); - if (path) { - lilv_dir_for_each(path, world, load_dir_entry); - free(path); - } -} - -static const char* -first_path_sep(const char* path) -{ - for (const char* p = path; *p != '\0'; ++p) { - if (*p == LILV_PATH_SEP[0]) { - return p; - } - } - return NULL; -} - -/** Load all bundles found in `lv2_path`. - * @param lv2_path A colon-delimited list of directories. These directories - * should contain LV2 bundle directories (ie the search path is a list of - * parent directories of bundles, not a list of bundle directories). - */ -static void -lilv_world_load_path(LilvWorld* world, - const char* lv2_path) -{ - while (lv2_path[0] != '\0') { - const char* const sep = first_path_sep(lv2_path); - if (sep) { - const size_t dir_len = sep - lv2_path; - char* const dir = (char*)malloc(dir_len + 1); - memcpy(dir, lv2_path, dir_len); - dir[dir_len] = '\0'; - lilv_world_load_directory(world, dir); - free(dir); - lv2_path += dir_len + 1; - } else { - lilv_world_load_directory(world, lv2_path); - lv2_path = "\0"; - } - } -} - -void -lilv_world_load_specifications(LilvWorld* world) -{ - for (LilvSpec* spec = world->specs; spec; spec = spec->next) { - LILV_FOREACH(nodes, f, spec->data_uris) { - LilvNode* file = (LilvNode*)lilv_collection_get(spec->data_uris, f); - lilv_world_load_graph(world, NULL, file); - } - } -} - -void -lilv_world_load_plugin_classes(LilvWorld* world) -{ - /* FIXME: This loads all classes, not just lv2:Plugin subclasses. - However, if the host gets all the classes via lilv_plugin_class_get_children - starting with lv2:Plugin as the root (which is e.g. how a host would build - a menu), they won't be seen anyway... - */ - - SordIter* classes = sord_search(world->model, - NULL, - world->uris.rdf_a, - world->uris.rdfs_Class, - NULL); - FOREACH_MATCH(classes) { - const SordNode* class_node = sord_iter_get_node(classes, SORD_SUBJECT); - - SordNode* parent = sord_get( - world->model, class_node, world->uris.rdfs_subClassOf, NULL, NULL); - if (!parent || sord_node_get_type(parent) != SORD_URI) { - continue; - } - - SordNode* label = sord_get( - world->model, class_node, world->uris.rdfs_label, NULL, NULL); - if (!label) { - sord_node_free(world->world, parent); - continue; - } - - LilvPluginClass* pclass = lilv_plugin_class_new( - world, parent, class_node, - (const char*)sord_node_get_string(label)); - if (pclass) { - zix_tree_insert((ZixTree*)world->plugin_classes, pclass, NULL); - } - - sord_node_free(world->world, label); - sord_node_free(world->world, parent); - } - sord_iter_free(classes); -} - -LILV_API void -lilv_world_load_all(LilvWorld* world, const char* lv2_path) -{ - // Discover bundles and read all manifest files into model - lilv_world_load_path(world, lv2_path); - - LILV_FOREACH(plugins, p, world->plugins) { - const LilvPlugin* plugin = (const LilvPlugin*)lilv_collection_get( - (ZixTree*)world->plugins, p); - - // ?new dc:replaces plugin - if (sord_ask(world->model, - NULL, - world->uris.dc_replaces, - lilv_plugin_get_uri(plugin)->node, - NULL)) { - // TODO: Check if replacement is a known plugin? (expensive) - ((LilvPlugin*)plugin)->replaced = true; - } - } - - // Query out things to cache - lilv_world_load_specifications(world); - lilv_world_load_plugin_classes(world); -} - -SerdStatus -lilv_world_load_file(LilvWorld* world, SerdReader* reader, const LilvNode* uri) -{ - ZixTreeIter* iter; - if (!zix_tree_find((ZixTree*)world->loaded_files, uri, &iter)) { - return SERD_FAILURE; // File has already been loaded - } - - serd_reader_add_blank_prefix(reader, lilv_world_blank_node_prefix(world)); - const SerdStatus st = serd_reader_read_file( - reader, sord_node_get_string(uri->node)); - if (st) { - LILV_ERRORF("Error loading file `%s'\n", lilv_node_as_string(uri)); - return st; - } - - zix_tree_insert((ZixTree*)world->loaded_files, - lilv_node_duplicate(uri), - NULL); - return SERD_SUCCESS; -} - -LILV_API int -lilv_world_load_resource(LilvWorld* world, - const LilvNode* resource) -{ - if (!lilv_node_is_uri(resource) && !lilv_node_is_blank(resource)) { - LILV_ERRORF("Node `%s' is not a resource\n", - sord_node_get_string(resource->node)); - return -1; - } - - SordModel* files = lilv_world_filter_model(world, - world->model, - resource->node, - world->uris.rdfs_seeAlso, - NULL, NULL); - - SordIter* f = sord_begin(files); - int n_read = 0; - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - const uint8_t* file_str = sord_node_get_string(file); - LilvNode* file_node = lilv_node_new_from_node(world, file); - if (sord_node_get_type(file) != SORD_URI) { - LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", file_str); - } else if (!lilv_world_load_graph(world, (SordNode*)file, file_node)) { - ++n_read; - } - lilv_node_free(file_node); - } - sord_iter_free(f); - - sord_free(files); - return n_read; -} - -LILV_API int -lilv_world_unload_resource(LilvWorld* world, - const LilvNode* resource) -{ - if (!lilv_node_is_uri(resource) && !lilv_node_is_blank(resource)) { - LILV_ERRORF("Node `%s' is not a resource\n", - sord_node_get_string(resource->node)); - return -1; - } - - SordModel* files = lilv_world_filter_model(world, - world->model, - resource->node, - world->uris.rdfs_seeAlso, - NULL, NULL); - - SordIter* f = sord_begin(files); - int n_dropped = 0; - FOREACH_MATCH(f) { - const SordNode* file = sord_iter_get_node(f, SORD_OBJECT); - LilvNode* file_node = lilv_node_new_from_node(world, file); - if (sord_node_get_type(file) != SORD_URI) { - LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", - sord_node_get_string(file)); - } else if (!lilv_world_drop_graph(world, file_node->node)) { - lilv_world_unload_file(world, file_node); - ++n_dropped; - } - lilv_node_free(file_node); - } - sord_iter_free(f); - - sord_free(files); - return n_dropped; -} - -LILV_API const LilvPluginClass* -lilv_world_get_plugin_class(const LilvWorld* world) -{ - return world->lv2_plugin_class; -} - -LILV_API const LilvPluginClasses* -lilv_world_get_plugin_classes(const LilvWorld* world) -{ - return world->plugin_classes; -} - -LILV_API const LilvPlugins* -lilv_world_get_all_plugins(const LilvWorld* world) -{ - return world->plugins; -} - -LILV_API LilvNode* -lilv_world_get_symbol(LilvWorld* world, const LilvNode* subject) -{ - // Check for explicitly given symbol - SordNode* snode = sord_get( - world->model, subject->node, world->uris.lv2_symbol, NULL, NULL); - - if (snode) { - LilvNode* ret = lilv_node_new_from_node(world, snode); - sord_node_free(world->world, snode); - return ret; - } - - if (!lilv_node_is_uri(subject)) { - return NULL; - } - - // Find rightmost segment of URI - SerdURI uri; - serd_uri_parse((const uint8_t*)lilv_node_as_uri(subject), &uri); - const char* str = "_"; - if (uri.fragment.buf) { - str = (const char*)uri.fragment.buf + 1; - } else if (uri.query.buf) { - str = (const char*)uri.query.buf; - } else if (uri.path.buf) { - const char* last_slash = strrchr((const char*)uri.path.buf, '/'); - str = last_slash ? (last_slash + 1) : (const char*)uri.path.buf; - } - - // Replace invalid characters - const size_t len = strlen(str); - char* const sym = (char*)calloc(1, len + 1); - for (size_t i = 0; i < len; ++i) { - const char c = str[i]; - if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || - (c == '_') || (i > 0 && c >= '0' && c <= '9'))) { - sym[i] = '_'; - } else { - sym[i] = str[i]; - } - } - - LilvNode* ret = lilv_new_string(world, sym); - free(sym); - return ret; -} diff --git a/source/modules/lilv/sratom-0.6.0/src/sratom.c.orig b/source/modules/lilv/sratom-0.6.0/src/sratom.c.orig deleted file mode 100644 index 0ea7fbb62..000000000 --- a/source/modules/lilv/sratom-0.6.0/src/sratom.c.orig +++ /dev/null @@ -1,835 +0,0 @@ -/* - Copyright 2012-2016 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 - -#include "lv2/lv2plug.in/ns/ext/atom/forge.h" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" - -#include "sratom/sratom.h" - -#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" - -#define USTR(str) ((const uint8_t*)(str)) - -static const SerdStyle style = (SerdStyle)( - SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED); - -typedef enum { - MODE_SUBJECT, - MODE_BODY, - MODE_SEQUENCE -} ReadMode; - -struct SratomImpl { - LV2_URID_Map* map; - LV2_Atom_Forge forge; - LV2_URID atom_Event; - LV2_URID atom_frameTime; - LV2_URID atom_beatTime; - LV2_URID midi_MidiEvent; - unsigned next_id; - SerdEnv* env; - SerdNode base_uri; - SerdURI base; - SerdStatementSink write_statement; - SerdEndSink end_anon; - void* handle; - SratomObjectMode object_mode; - bool pretty_numbers; - uint32_t seq_unit; - struct { - SordNode* atom_childType; - SordNode* atom_frameTime; - SordNode* atom_beatTime; - SordNode* rdf_first; - SordNode* rdf_rest; - SordNode* rdf_type; - SordNode* rdf_value; - SordNode* xsd_base64Binary; - } nodes; -}; - -static void -read_node(Sratom* sratom, - LV2_Atom_Forge* forge, - SordWorld* world, - SordModel* model, - const SordNode* node, - ReadMode mode); - -SRATOM_API -Sratom* -sratom_new(LV2_URID_Map* map) -{ - Sratom* sratom = (Sratom*)calloc(1, sizeof(Sratom)); - if (sratom) { - sratom->map = map; - sratom->atom_Event = map->map(map->handle, LV2_ATOM__Event); - sratom->atom_frameTime = map->map(map->handle, LV2_ATOM__frameTime); - sratom->atom_beatTime = map->map(map->handle, LV2_ATOM__beatTime); - sratom->midi_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent); - sratom->object_mode = SRATOM_OBJECT_MODE_BLANK; - lv2_atom_forge_init(&sratom->forge, map); - } - return sratom; -} - -SRATOM_API -void -sratom_free(Sratom* sratom) -{ - serd_node_free(&sratom->base_uri); - free(sratom); -} - -SRATOM_API -void -sratom_set_env(Sratom* sratom, SerdEnv* env) -{ - sratom->env = env; -} - -SRATOM_API -void -sratom_set_sink(Sratom* sratom, - const char* base_uri, - SerdStatementSink write_statement, - SerdEndSink end_anon, - void* handle) -{ - if (base_uri) { - serd_node_free(&sratom->base_uri); - sratom->base_uri = serd_node_new_uri_from_string( - USTR(base_uri), NULL, NULL); - serd_uri_parse(sratom->base_uri.buf, &sratom->base); - } - sratom->write_statement = write_statement; - sratom->end_anon = end_anon; - sratom->handle = handle; -} - -SRATOM_API -void -sratom_set_pretty_numbers(Sratom* sratom, - bool pretty_numbers) -{ - sratom->pretty_numbers = pretty_numbers; -} - -SRATOM_API -void -sratom_set_object_mode(Sratom* sratom, - SratomObjectMode object_mode) -{ - sratom->object_mode = object_mode; -} - -static void -gensym(SerdNode* out, char c, unsigned num) -{ - out->n_bytes = out->n_chars = snprintf( - (char*)out->buf, 10, "%c%u", c, num); -} - -static void -list_append(Sratom* sratom, - LV2_URID_Unmap* unmap, - unsigned* flags, - SerdNode* s, - SerdNode* p, - SerdNode* node, - uint32_t size, - uint32_t type, - const void* body) -{ - // Generate a list node - gensym(node, 'l', sratom->next_id); - sratom->write_statement(sratom->handle, *flags, NULL, - s, p, node, NULL, NULL); - - // _:node rdf:first value - *flags = SERD_LIST_CONT; - *p = serd_node_from_string(SERD_URI, NS_RDF "first"); - sratom_write(sratom, unmap, *flags, node, p, type, size, body); - - // Set subject to node and predicate to rdf:rest for next time - gensym(node, 'l', ++sratom->next_id); - *s = *node; - *p = serd_node_from_string(SERD_URI, NS_RDF "rest"); -} - -static void -list_end(SerdStatementSink sink, - void* handle, - unsigned* flags, - SerdNode* s, - SerdNode* p) -{ - // _:node rdf:rest rdf:nil - const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil"); - sink(handle, *flags, NULL, s, p, &nil, NULL, NULL); -} - -static void -start_object(Sratom* sratom, - uint32_t* flags, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* node, - const char* type) -{ - if (subject && predicate) { - sratom->write_statement(sratom->handle, *flags|SERD_ANON_O_BEGIN, NULL, - subject, predicate, node, NULL, NULL); - // Start abbreviating object properties - *flags |= SERD_ANON_CONT; - - // Object is in a list, stop list abbreviating if necessary - *flags &= ~SERD_LIST_CONT; - } - if (type) { - SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "type"); - SerdNode o = serd_node_from_string(SERD_URI, USTR(type)); - sratom->write_statement(sratom->handle, *flags, NULL, - node, &p, &o, NULL, NULL); - } -} - -static bool -path_is_absolute(const char* path) -{ - return (path[0] == '/' - || (isalpha(path[0]) && path[1] == ':' - && (path[2] == '/' || path[2] == '\\'))); -} - -static SerdNode -number_type(const Sratom* sratom, const uint8_t* type) -{ - if (sratom->pretty_numbers && - (!strcmp((const char*)type, (const char*)NS_XSD "int") || - !strcmp((const char*)type, (const char*)NS_XSD "long"))) { - return serd_node_from_string(SERD_URI, NS_XSD "integer"); - } else if (sratom->pretty_numbers && - (!strcmp((const char*)type, (const char*)NS_XSD "float") || - !strcmp((const char*)type, (const char*)NS_XSD "double"))) { - return serd_node_from_string(SERD_URI, NS_XSD "decimal"); - } else { - return serd_node_from_string(SERD_URI, (const uint8_t*)type); - } -} - -SRATOM_API -int -sratom_write(Sratom* sratom, - LV2_URID_Unmap* unmap, - uint32_t flags, - const SerdNode* subject, - const SerdNode* predicate, - uint32_t type_urid, - uint32_t size, - const void* body) -{ - const char* const type = unmap->unmap(unmap->handle, type_urid); - uint8_t idbuf[12] = "b0000000000"; - SerdNode id = serd_node_from_string(SERD_BLANK, idbuf); - uint8_t nodebuf[12] = "b0000000000"; - SerdNode node = serd_node_from_string(SERD_BLANK, nodebuf); - SerdNode object = SERD_NODE_NULL; - SerdNode datatype = SERD_NODE_NULL; - SerdNode language = SERD_NODE_NULL; - bool new_node = false; - if (type_urid == 0 && size == 0) { - object = serd_node_from_string(SERD_URI, USTR(NS_RDF "nil")); - } else if (type_urid == sratom->forge.String) { - object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body); - } else if (type_urid == sratom->forge.Chunk) { - datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary"); - object = serd_node_new_blob(body, size, true); - new_node = true; - } else if (type_urid == sratom->forge.Literal) { - const LV2_Atom_Literal_Body* lit = (const LV2_Atom_Literal_Body*)body; - const uint8_t* str = USTR(lit + 1); - object = serd_node_from_string(SERD_LITERAL, str); - if (lit->datatype) { - datatype = serd_node_from_string( - SERD_URI, USTR(unmap->unmap(unmap->handle, lit->datatype))); - } else if (lit->lang) { - const char* lang = unmap->unmap(unmap->handle, lit->lang); - const char* prefix = "http://lexvo.org/id/iso639-3/"; - const size_t prefix_len = strlen(prefix); - if (lang && !strncmp(lang, prefix, prefix_len)) { - language = serd_node_from_string( - SERD_LITERAL, USTR(lang + prefix_len)); - } else { - fprintf(stderr, "Unknown language URID %d\n", lit->lang); - } - } - } else if (type_urid == sratom->forge.URID) { - const uint32_t urid = *(const uint32_t*)body; - const uint8_t* str = USTR(unmap->unmap(unmap->handle, urid)); - object = serd_node_from_string(SERD_URI, str); - } else if (type_urid == sratom->forge.Path) { - const uint8_t* str = USTR(body); - if (path_is_absolute((const char*)str)) { - new_node = true; - object = serd_node_new_file_uri(str, NULL, NULL, true); - } else { - if (!sratom->base_uri.buf || - strncmp((const char*)sratom->base_uri.buf, "file://", 7)) { - fprintf(stderr, "warning: Relative path but base is not a file URI.\n"); - fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n"); - object = serd_node_from_string(SERD_LITERAL, str); - datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path)); - } else { - new_node = true; - SerdNode rel = serd_node_new_file_uri(str, NULL, NULL, true); - object = serd_node_new_uri_from_node(&rel, &sratom->base, NULL); - serd_node_free(&rel); - } - } - } else if (type_urid == sratom->forge.URI) { - const uint8_t* str = USTR(body); - object = serd_node_from_string(SERD_URI, str); - } else if (type_urid == sratom->forge.Int) { - new_node = true; - object = serd_node_new_integer(*(const int32_t*)body); - datatype = number_type(sratom, NS_XSD "int"); - } else if (type_urid == sratom->forge.Long) { - new_node = true; - object = serd_node_new_integer(*(const int64_t*)body); - datatype = number_type(sratom, NS_XSD "long"); - } else if (type_urid == sratom->forge.Float) { - new_node = true; - object = serd_node_new_decimal(*(const float*)body, 8); - datatype = number_type(sratom, NS_XSD "float"); - } else if (type_urid == sratom->forge.Double) { - new_node = true; - object = serd_node_new_decimal(*(const double*)body, 16); - datatype = number_type(sratom, NS_XSD "double"); - } else if (type_urid == sratom->forge.Bool) { - const int32_t val = *(const int32_t*)body; - datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean"); - object = serd_node_from_string(SERD_LITERAL, - USTR(val ? "true" : "false")); - } else if (type_urid == sratom->midi_MidiEvent) { - new_node = true; - datatype = serd_node_from_string(SERD_URI, USTR(LV2_MIDI__MidiEvent)); - uint8_t* str = (uint8_t*)calloc(size * 2 + 1, 1); - for (uint32_t i = 0; i < size; ++i) { - snprintf((char*)str + (2 * i), size * 2 + 1, "%02X", - (unsigned)(uint8_t)*((const uint8_t*)body + i)); - } - object = serd_node_from_string(SERD_LITERAL, USTR(str)); - } else if (type_urid == sratom->atom_Event) { - const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body; - gensym(&id, 'e', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, NULL); - SerdNode time; - SerdNode p; - if (sratom->seq_unit == sratom->atom_beatTime) { - time = serd_node_new_decimal(ev->time.beats, 16); - p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__beatTime)); - datatype = number_type(sratom, NS_XSD "double"); - } else { - time = serd_node_new_integer(ev->time.frames); - p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__frameTime)); - datatype = number_type(sratom, NS_XSD "long"); - } - sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL, - &id, &p, &time, &datatype, &language); - serd_node_free(&time); - - p = serd_node_from_string(SERD_URI, NS_RDF "value"); - sratom_write(sratom, unmap, SERD_ANON_CONT, &id, &p, - ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body)); - if (sratom->end_anon) { - sratom->end_anon(sratom->handle, &id); - } - } else if (type_urid == sratom->forge.Tuple) { - gensym(&id, 't', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, type); - SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); - flags |= SERD_LIST_O_BEGIN; - LV2_ATOM_TUPLE_BODY_FOREACH(body, size, i) { - list_append(sratom, unmap, &flags, &id, &p, &node, - i->size, i->type, LV2_ATOM_BODY(i)); - } - list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); - if (sratom->end_anon) { - sratom->end_anon(sratom->handle, &id); - } - } else if (type_urid == sratom->forge.Vector) { - const LV2_Atom_Vector_Body* vec = (const LV2_Atom_Vector_Body*)body; - gensym(&id, 'v', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, type); - SerdNode p = serd_node_from_string(SERD_URI, (const uint8_t*)LV2_ATOM__childType); - SerdNode child_type = serd_node_from_string( - SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, vec->child_type)); - sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &child_type, NULL, NULL); - p = serd_node_from_string(SERD_URI, NS_RDF "value"); - flags |= SERD_LIST_O_BEGIN; - for (const char* i = (const char*)(vec + 1); - i < (const char*)vec + size; - i += vec->child_size) { - list_append(sratom, unmap, &flags, &id, &p, &node, - vec->child_size, vec->child_type, i); - } - list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); - if (sratom->end_anon) { - sratom->end_anon(sratom->handle, &id); - } - } else if (lv2_atom_forge_is_object_type(&sratom->forge, type_urid)) { - const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body; - const char* otype = unmap->unmap(unmap->handle, - obj->otype); - - if (lv2_atom_forge_is_blank(&sratom->forge, type_urid, obj)) { - gensym(&id, 'b', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, otype); - } else { - id = serd_node_from_string( - SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, obj->id)); - flags = 0; - start_object(sratom, &flags, NULL, NULL, &id, otype); - } - LV2_ATOM_OBJECT_BODY_FOREACH(obj, size, prop) { - const char* const key = unmap->unmap(unmap->handle, prop->key); - SerdNode pred = serd_node_from_string(SERD_URI, USTR(key)); - sratom_write(sratom, unmap, flags, &id, &pred, - prop->value.type, prop->value.size, - LV2_ATOM_BODY(&prop->value)); - } - if (sratom->end_anon && (flags & SERD_ANON_CONT)) { - sratom->end_anon(sratom->handle, &id); - } - } else if (type_urid == sratom->forge.Sequence) { - const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body; - gensym(&id, 'v', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, type); - SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); - flags |= SERD_LIST_O_BEGIN; - LV2_ATOM_SEQUENCE_BODY_FOREACH(seq, size, ev) { - sratom->seq_unit = seq->unit; - list_append(sratom, unmap, &flags, &id, &p, &node, - sizeof(LV2_Atom_Event) + ev->body.size, - sratom->atom_Event, - ev); - } - list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); - if (sratom->end_anon && subject && predicate) { - sratom->end_anon(sratom->handle, &id); - } - } else { - gensym(&id, 'b', sratom->next_id++); - start_object(sratom, &flags, subject, predicate, &id, type); - SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); - SerdNode o = serd_node_new_blob(body, size, true); - datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary"); - sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &o, &datatype, NULL); - if (sratom->end_anon && subject && predicate) { - sratom->end_anon(sratom->handle, &id); - } - serd_node_free(&o); - } - - if (object.buf) { - SerdNode def_s = serd_node_from_string(SERD_BLANK, USTR("atom")); - SerdNode def_p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value")); - if (!subject) { - subject = &def_s; - } - if (!predicate) { - predicate = &def_p; - } - sratom->write_statement(sratom->handle, flags, NULL, - subject, predicate, &object, &datatype, &language); - } - - if (new_node) { - serd_node_free(&object); - } - - return 0; -} - -SRATOM_API -char* -sratom_to_turtle(Sratom* sratom, - LV2_URID_Unmap* unmap, - const char* base_uri, - const SerdNode* subject, - const SerdNode* predicate, - uint32_t type, - uint32_t size, - const void* body) -{ - SerdURI buri = SERD_URI_NULL; - SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), &sratom->base, &buri); - SerdEnv* env = sratom->env ? sratom->env : serd_env_new(NULL); - SerdChunk str = { NULL, 0 }; - SerdWriter* writer = serd_writer_new( - SERD_TURTLE, style, env, &buri, serd_chunk_sink, &str); - - serd_env_set_base_uri(env, &base); - sratom_set_sink(sratom, base_uri, - (SerdStatementSink)serd_writer_write_statement, - (SerdEndSink)serd_writer_end_anon, - writer); - sratom_write(sratom, unmap, SERD_EMPTY_S, - subject, predicate, type, size, body); - serd_writer_finish(writer); - - serd_writer_free(writer); - if (!sratom->env) { - serd_env_free(env); - } - serd_node_free(&base); - return (char*)serd_chunk_sink_finish(&str); -} - -static void -read_list_value(Sratom* sratom, - LV2_Atom_Forge* forge, - SordWorld* world, - SordModel* model, - const SordNode* node, - ReadMode mode) -{ - SordNode* fst = sord_get(model, node, sratom->nodes.rdf_first, NULL, NULL); - SordNode* rst = sord_get(model, node, sratom->nodes.rdf_rest, NULL, NULL); - if (fst && rst) { - read_node(sratom, forge, world, model, fst, mode); - read_list_value(sratom, forge, world, model, rst, mode); - } - sord_node_free(world, rst); - sord_node_free(world, fst); -} - -static void -read_resource(Sratom* sratom, - LV2_Atom_Forge* forge, - SordWorld* world, - SordModel* model, - const SordNode* node, - LV2_URID otype) -{ - LV2_URID_Map* map = sratom->map; - SordQuad q = { node, NULL, NULL, NULL }; - SordIter* i = sord_find(model, q); - SordQuad match; - for (; !sord_iter_end(i); sord_iter_next(i)) { - sord_iter_get(i, match); - const SordNode* p = match[SORD_PREDICATE]; - const SordNode* o = match[SORD_OBJECT]; - const char* p_uri = (const char*)sord_node_get_string(p); - uint32_t p_urid = map->map(map->handle, p_uri); - if (!(sord_node_equals(p, sratom->nodes.rdf_type) && - sord_node_get_type(o) == SORD_URI && - map->map(map->handle, (const char*)sord_node_get_string(o)) == otype)) { - lv2_atom_forge_key(forge, p_urid); - read_node(sratom, forge, world, model, o, MODE_BODY); - } - } - sord_iter_free(i); -} - -static uint32_t -atom_size(Sratom* sratom, uint32_t type_urid) -{ - if (type_urid == sratom->forge.Int) { - return sizeof(int32_t); - } else if (type_urid == sratom->forge.Long) { - return sizeof(int64_t); - } else if (type_urid == sratom->forge.Float) { - return sizeof(float); - } else if (type_urid == sratom->forge.Double) { - return sizeof(double); - } else if (type_urid == sratom->forge.Bool) { - return sizeof(int32_t); - } else if (type_urid == sratom->forge.URID) { - return sizeof(uint32_t); - } - return 0; -} - -static void -read_node(Sratom* sratom, - LV2_Atom_Forge* forge, - SordWorld* world, - SordModel* model, - const SordNode* node, - ReadMode mode) -{ - LV2_URID_Map* map = sratom->map; - size_t len = 0; - const char* str = (const char*)sord_node_get_string_counted(node, &len); - if (sord_node_get_type(node) == SORD_LITERAL) { - SordNode* datatype = sord_node_get_datatype(node); - const char* language = sord_node_get_language(node); - if (datatype) { - const char* type_uri = (const char*)sord_node_get_string(datatype); - if (!strcmp(type_uri, (const char*)NS_XSD "int") || - !strcmp(type_uri, (const char*)NS_XSD "integer")) { - lv2_atom_forge_int(forge, strtol(str, NULL, 10)); - } else if (!strcmp(type_uri, (const char*)NS_XSD "long")) { - lv2_atom_forge_long(forge, strtol(str, NULL, 10)); - } else if (!strcmp(type_uri, (const char*)NS_XSD "float") || - !strcmp(type_uri, (const char*)NS_XSD "decimal")) { - lv2_atom_forge_float(forge, serd_strtod(str, NULL)); - } else if (!strcmp(type_uri, (const char*)NS_XSD "double")) { - lv2_atom_forge_double(forge, serd_strtod(str, NULL)); - } else if (!strcmp(type_uri, (const char*)NS_XSD "boolean")) { - lv2_atom_forge_bool(forge, !strcmp(str, "true")); - } else if (!strcmp(type_uri, (const char*)NS_XSD "base64Binary")) { - size_t size = 0; - void* body = serd_base64_decode(USTR(str), len, &size); - lv2_atom_forge_atom(forge, size, forge->Chunk); - lv2_atom_forge_write(forge, body, size); - free(body); - } else if (!strcmp(type_uri, LV2_ATOM__Path)) { - lv2_atom_forge_path(forge, str, len); - } else if (!strcmp(type_uri, LV2_MIDI__MidiEvent)) { - lv2_atom_forge_atom(forge, len / 2, sratom->midi_MidiEvent); - for (const char* s = str; s < str + len; s += 2) { - unsigned num; - sscanf(s, "%2X", &num); - const uint8_t c = num; - lv2_atom_forge_raw(forge, &c, 1); - } - lv2_atom_forge_pad(forge, len / 2); - } else { - lv2_atom_forge_literal( - forge, str, len, - sratom->map->map(sratom->map->handle, type_uri), - 0); - } - } else if (language) { - const char* prefix = "http://lexvo.org/id/iso639-3/"; - const size_t lang_len = strlen(prefix) + strlen(language); - char* lang_uri = (char*)calloc(lang_len + 1, 1); - snprintf(lang_uri, lang_len + 1, "%s%s", prefix, language); - lv2_atom_forge_literal( - forge, str, len, 0, - sratom->map->map(sratom->map->handle, lang_uri)); - free(lang_uri); - } else { - lv2_atom_forge_string(forge, str, len); - } - } else if (sord_node_get_type(node) == SORD_URI && - !(sratom->object_mode == SRATOM_OBJECT_MODE_BLANK_SUBJECT - && mode == MODE_SUBJECT)) { - if (!strcmp(str, (const char*)NS_RDF "nil")) { - lv2_atom_forge_atom(forge, 0, 0); - } else if (!strncmp(str, "file://", 7)) { - SerdURI uri; - serd_uri_parse((const uint8_t*)str, &uri); - - SerdNode rel = serd_node_new_relative_uri(&uri, &sratom->base, NULL, NULL); - uint8_t* path = serd_file_uri_parse(rel.buf, NULL); - lv2_atom_forge_path(forge, (const char*)path, strlen((const char*)path)); - free(path); - serd_node_free(&rel); - } else { - lv2_atom_forge_urid(forge, map->map(map->handle, str)); - } - } else { - SordNode* type = sord_get( - model, node, sratom->nodes.rdf_type, NULL, NULL); - SordNode* value = sord_get( - model, node, sratom->nodes.rdf_value, NULL, NULL); - - const uint8_t* type_uri = NULL; - uint32_t type_urid = 0; - if (type) { - type_uri = sord_node_get_string(type); - type_urid = map->map(map->handle, (const char*)type_uri); - } - - LV2_Atom_Forge_Frame frame = { 0, 0 }; - if (mode == MODE_SEQUENCE) { - SordNode* time = sord_get( - model, node, sratom->nodes.atom_beatTime, NULL, NULL); - uint32_t seq_unit; - if (time) { - const char* time_str = (const char*)sord_node_get_string(time); - lv2_atom_forge_beat_time(forge, serd_strtod(time_str, NULL)); - seq_unit = sratom->atom_beatTime; - } else { - time = sord_get(model, node, sratom->nodes.atom_frameTime, NULL, NULL); - const char* time_str = time - ? (const char*)sord_node_get_string(time) - : ""; - lv2_atom_forge_frame_time(forge, serd_strtod(time_str, NULL)); - seq_unit = sratom->atom_frameTime; - } - read_node(sratom, forge, world, model, value, MODE_BODY); - sord_node_free(world, time); - sratom->seq_unit = seq_unit; - } else if (type_urid == sratom->forge.Tuple) { - lv2_atom_forge_tuple(forge, &frame); - read_list_value(sratom, forge, world, model, value, MODE_BODY); - } else if (type_urid == sratom->forge.Sequence) { - const LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0); - sratom->seq_unit = 0; - read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE); - - LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)lv2_atom_forge_deref(forge, ref); - seq->body.unit = (sratom->seq_unit == sratom->atom_frameTime) ? 0 : sratom->seq_unit; - } else if (type_urid == sratom->forge.Vector) { - SordNode* child_type_node = sord_get( - model, node, sratom->nodes.atom_childType, NULL, NULL); - uint32_t child_type = map->map( - map->handle, (const char*)sord_node_get_string(child_type_node)); - uint32_t child_size = atom_size(sratom, child_type); - if (child_size > 0) { - LV2_Atom_Forge_Ref ref = lv2_atom_forge_vector_head( - forge, &frame, child_size, child_type); - read_list_value(sratom, forge, world, model, value, MODE_BODY); - lv2_atom_forge_pop(forge, &frame); - frame.ref = 0; - lv2_atom_forge_pad(forge, lv2_atom_forge_deref(forge, ref)->size); - } - sord_node_free(world, child_type_node); - } else if (value && sord_node_equals(sord_node_get_datatype(value), - sratom->nodes.xsd_base64Binary)) { - size_t vlen = 0; - const uint8_t* vstr = sord_node_get_string_counted(value, &vlen); - size_t size = 0; - void* body = serd_base64_decode(vstr, vlen, &size); - lv2_atom_forge_atom(forge, size, type_urid); - lv2_atom_forge_write(forge, body, size); - free(body); - } else if (sord_node_get_type(node) == SORD_URI) { - lv2_atom_forge_object( - forge, &frame, map->map(map->handle, str), type_urid); - read_resource(sratom, forge, world, model, node, type_urid); - } else { - lv2_atom_forge_object(forge, &frame, 0, type_urid); - read_resource(sratom, forge, world, model, node, type_urid); - } - - if (frame.ref) { - lv2_atom_forge_pop(forge, &frame); - } - sord_node_free(world, value); - sord_node_free(world, type); - } -} - -SRATOM_API -void -sratom_read(Sratom* sratom, - LV2_Atom_Forge* forge, - SordWorld* world, - SordModel* model, - const SordNode* node) -{ - sratom->nodes.atom_childType = sord_new_uri(world, USTR(LV2_ATOM__childType)); - sratom->nodes.atom_frameTime = sord_new_uri(world, USTR(LV2_ATOM__frameTime)); - sratom->nodes.atom_beatTime = sord_new_uri(world, USTR(LV2_ATOM__beatTime)); - sratom->nodes.rdf_first = sord_new_uri(world, NS_RDF "first"); - sratom->nodes.rdf_rest = sord_new_uri(world, NS_RDF "rest"); - sratom->nodes.rdf_type = sord_new_uri(world, NS_RDF "type"); - sratom->nodes.rdf_value = sord_new_uri(world, NS_RDF "value"); - sratom->nodes.xsd_base64Binary = sord_new_uri(world, NS_XSD "base64Binary"); - - sratom->next_id = 1; - read_node(sratom, forge, world, model, node, MODE_SUBJECT); - - sord_node_free(world, sratom->nodes.xsd_base64Binary); - sord_node_free(world, sratom->nodes.rdf_value); - sord_node_free(world, sratom->nodes.rdf_type); - sord_node_free(world, sratom->nodes.rdf_rest); - sord_node_free(world, sratom->nodes.rdf_first); - sord_node_free(world, sratom->nodes.atom_frameTime); - sord_node_free(world, sratom->nodes.atom_beatTime); - sord_node_free(world, sratom->nodes.atom_childType); - memset(&sratom->nodes, 0, sizeof(sratom->nodes)); -} - -SRATOM_API -LV2_Atom_Forge_Ref -sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle, - const void* buf, - uint32_t size) -{ - SerdChunk* chunk = (SerdChunk*)handle; - const LV2_Atom_Forge_Ref ref = chunk->len + 1; - serd_chunk_sink(buf, size, chunk); - return ref; -} - -SRATOM_API -LV2_Atom* -sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref) -{ - SerdChunk* chunk = (SerdChunk*)handle; - return (LV2_Atom*)(chunk->buf + ref - 1); -} - -SRATOM_API -LV2_Atom* -sratom_from_turtle(Sratom* sratom, - const char* base_uri, - const SerdNode* subject, - const SerdNode* predicate, - const char* str) -{ - SerdChunk out = { NULL, 0 }; - SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), &sratom->base, NULL); - SordWorld* world = sord_world_new(); - SordModel* model = sord_new(world, SORD_SPO, false); - SerdEnv* env = sratom->env ? sratom->env : serd_env_new(&base); - SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); - - if (!serd_reader_read_string(reader, (const uint8_t*)str)) { - SordNode* s = sord_node_from_serd_node(world, env, subject, 0, 0); - lv2_atom_forge_set_sink( - &sratom->forge, sratom_forge_sink, sratom_forge_deref, &out); - if (subject && predicate) { - SordNode* p = sord_node_from_serd_node(world, env, predicate, 0, 0); - SordNode* o = sord_get(model, s, p, NULL, NULL); - if (o) { - sratom_read(sratom, &sratom->forge, world, model, o); - sord_node_free(world, o); - } else { - fprintf(stderr, "Failed to find node\n"); - } - } else { - sratom_read(sratom, &sratom->forge, world, model, s); - } - } else { - fprintf(stderr, "Failed to read Turtle\n"); - } - - serd_reader_free(reader); - if (!sratom->env) { - serd_env_free(env); - } - sord_free(model); - sord_world_free(world); - serd_node_free(&base); - - return (LV2_Atom*)out.buf; -}