| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| /* | ||
| Copyright 2008-2011 David Robillard <http://drobilla.net> | ||
| 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. | ||
| */ | ||
|
|
||
| /** | ||
| @defgroup uri-map URI Map | ||
| C API for the LV2 URI Map extension <http://lv2plug.in/ns/ext/uri-map>. | ||
| This extension defines a simple mechanism for plugins to map URIs to | ||
| integers, usually for performance reasons (e.g. processing events typed by | ||
| URIs in real time). The expected use case is for plugins to map URIs to | ||
| integers for things they 'understand' at instantiation time, and store those | ||
| values for use in the audio thread without doing any string comparison. | ||
| This allows the extensibility of RDF with the performance of integers (or | ||
| centrally defined enumerations). | ||
| @{ | ||
| */ | ||
|
|
||
| #ifndef LV2_URI_MAP_H | ||
| #define LV2_URI_MAP_H | ||
|
|
||
| #define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map" | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| Opaque pointer to host data. | ||
| */ | ||
| typedef void* LV2_URI_Map_Callback_Data; | ||
|
|
||
| /** | ||
| URI Map Feature. | ||
| To support this feature the host must pass an LV2_Feature struct to the | ||
| plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-map" | ||
| and data pointed to an instance of this struct. | ||
| */ | ||
| typedef struct { | ||
| /** | ||
| Opaque pointer to host data. | ||
| The plugin MUST pass this to any call to functions in this struct. | ||
| Otherwise, it must not be interpreted in any way. | ||
| */ | ||
| LV2_URI_Map_Callback_Data callback_data; | ||
|
|
||
| /** | ||
| Get the numeric ID of a URI from the host. | ||
| @param callback_data Must be the callback_data member of this struct. | ||
| @param map The 'context' of this URI. Certain extensions may define a | ||
| URI that must be passed here with certain restrictions on the return | ||
| value (e.g. limited range). This value may be NULL if the plugin needs | ||
| an ID for a URI in general. Extensions SHOULD NOT define a context | ||
| unless there is a specific need to do so, e.g. to restrict the range of | ||
| the returned value. | ||
| @param uri The URI to be mapped to an integer ID. | ||
| This function is referentially transparent; any number of calls with the | ||
| same arguments is guaranteed to return the same value over the life of a | ||
| plugin instance (though the same URI may return different values with a | ||
| different map parameter). However, this function is not necessarily very | ||
| fast: plugins SHOULD cache any IDs they might need in performance | ||
| critical situations. | ||
| The return value 0 is reserved and indicates that an ID for that URI | ||
| could not be created for whatever reason. Extensions MAY define more | ||
| precisely what this means in a certain context, but in general plugins | ||
| SHOULD handle this situation as gracefully as possible. However, hosts | ||
| SHOULD NOT return 0 from this function in non-exceptional circumstances | ||
| (e.g. the URI map SHOULD be dynamic). Hosts that statically support only | ||
| a fixed set of URIs should not expect plugins to function correctly. | ||
| */ | ||
| uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data, | ||
| const char* map, | ||
| const char* uri); | ||
| } LV2_URI_Map_Feature; | ||
|
|
||
| #ifdef __cplusplus | ||
| } /* extern "C" */ | ||
| #endif | ||
|
|
||
| #endif /* LV2_URI_MAP_H */ | ||
|
|
||
| /** | ||
| @} | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /* | ||
| Copyright 2008-2012 David Robillard <http://drobilla.net> | ||
| Copyright 2011 Gabriel M. Beddingfield <gabrbedd@gmail.com> | ||
| 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. | ||
| */ | ||
|
|
||
| /** | ||
| @defgroup urid URID | ||
| Features for mapping URIs to and from integers, see | ||
| <http://lv2plug.in/ns/ext/urid> for details. | ||
| @{ | ||
| */ | ||
|
|
||
| #ifndef LV2_URID_H | ||
| #define LV2_URID_H | ||
|
|
||
| #define LV2_URID_URI "http://lv2plug.in/ns/ext/urid" | ||
| #define LV2_URID_PREFIX LV2_URID_URI "#" | ||
|
|
||
| #define LV2_URID__map LV2_URID_PREFIX "map" | ||
| #define LV2_URID__unmap LV2_URID_PREFIX "unmap" | ||
|
|
||
| /* Legacy defines */ | ||
| #define LV2_URID_MAP_URI LV2_URID__map | ||
| #define LV2_URID_UNMAP_URI LV2_URID__unmap | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| Opaque pointer to host data for LV2_URID_Map. | ||
| */ | ||
| typedef void* LV2_URID_Map_Handle; | ||
|
|
||
| /** | ||
| Opaque pointer to host data for LV2_URID_Unmap. | ||
| */ | ||
| typedef void* LV2_URID_Unmap_Handle; | ||
|
|
||
| /** | ||
| URI mapped to an integer. | ||
| */ | ||
| typedef uint32_t LV2_URID; | ||
|
|
||
| /** | ||
| URID Map Feature (LV2_URID__map) | ||
| */ | ||
| typedef struct _LV2_URID_Map { | ||
| /** | ||
| Opaque pointer to host data. | ||
| This MUST be passed to map_uri() whenever it is called. | ||
| Otherwise, it must not be interpreted in any way. | ||
| */ | ||
| LV2_URID_Map_Handle handle; | ||
|
|
||
| /** | ||
| Get the numeric ID of a URI. | ||
| If the ID does not already exist, it will be created. | ||
| This function is referentially transparent; any number of calls with the | ||
| same arguments is guaranteed to return the same value over the life of a | ||
| plugin instance. Note, however, that several URIs MAY resolve to the | ||
| same ID if the host considers those URIs equivalent. | ||
| This function is not necessarily very fast or RT-safe: plugins SHOULD | ||
| cache any IDs they might need in performance critical situations. | ||
| The return value 0 is reserved and indicates that an ID for that URI | ||
| could not be created for whatever reason. However, hosts SHOULD NOT | ||
| return 0 from this function in non-exceptional circumstances (i.e. the | ||
| URI map SHOULD be dynamic). | ||
| @param handle Must be the callback_data member of this struct. | ||
| @param uri The URI to be mapped to an integer ID. | ||
| */ | ||
| LV2_URID (*map)(LV2_URID_Map_Handle handle, | ||
| const char* uri); | ||
| } LV2_URID_Map; | ||
|
|
||
| /** | ||
| URI Unmap Feature (LV2_URID__unmap) | ||
| */ | ||
| typedef struct _LV2_URID_Unmap { | ||
| /** | ||
| Opaque pointer to host data. | ||
| This MUST be passed to unmap() whenever it is called. | ||
| Otherwise, it must not be interpreted in any way. | ||
| */ | ||
| LV2_URID_Unmap_Handle handle; | ||
|
|
||
| /** | ||
| Get the URI for a previously mapped numeric ID. | ||
| Returns NULL if `urid` is not yet mapped. Otherwise, the corresponding | ||
| URI is returned in a canonical form. This MAY not be the exact same | ||
| string that was originally passed to LV2_URID_Map::map(), but it MUST be | ||
| an identical URI according to the URI syntax specification (RFC3986). A | ||
| non-NULL return for a given `urid` will always be the same for the life | ||
| of the plugin. Plugins that intend to perform string comparison on | ||
| unmapped URIs SHOULD first canonicalise URI strings with a call to | ||
| map_uri() followed by a call to unmap_uri(). | ||
| @param handle Must be the callback_data member of this struct. | ||
| @param urid The ID to be mapped back to the URI string. | ||
| */ | ||
| const char* (*unmap)(LV2_URID_Unmap_Handle handle, | ||
| LV2_URID urid); | ||
| } LV2_URID_Unmap; | ||
|
|
||
| #ifdef __cplusplus | ||
| } /* extern "C" */ | ||
| #endif | ||
|
|
||
| #endif /* LV2_URID_H */ | ||
|
|
||
| /** | ||
| @} | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| /* | ||
| Copyright 2012 David Robillard <http://drobilla.net> | ||
| 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. | ||
| */ | ||
|
|
||
| /** | ||
| @defgroup worker Worker | ||
| Support for non-realtime plugin operations, see | ||
| <http://lv2plug.in/ns/ext/worker> for details. | ||
| @{ | ||
| */ | ||
|
|
||
| #ifndef LV2_WORKER_H | ||
| #define LV2_WORKER_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #include "lv2/lv2plug.in/ns/lv2core/lv2.h" | ||
|
|
||
| #define LV2_WORKER_URI "http://lv2plug.in/ns/ext/worker" | ||
| #define LV2_WORKER_PREFIX LV2_WORKER_URI "#" | ||
|
|
||
| #define LV2_WORKER__interface LV2_WORKER_PREFIX "interface" | ||
| #define LV2_WORKER__schedule LV2_WORKER_PREFIX "schedule" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| Status code for worker functions. | ||
| */ | ||
| typedef enum { | ||
| LV2_WORKER_SUCCESS = 0, /**< Completed successfully. */ | ||
| LV2_WORKER_ERR_UNKNOWN = 1, /**< Unknown error. */ | ||
| LV2_WORKER_ERR_NO_SPACE = 2 /**< Failed due to lack of space. */ | ||
| } LV2_Worker_Status; | ||
|
|
||
| /** Opaque handle for LV2_Worker_Interface::work(). */ | ||
| typedef void* LV2_Worker_Respond_Handle; | ||
|
|
||
| /** | ||
| A function to respond to run() from the worker method. | ||
| The `data` MUST be safe for the host to copy and later pass to | ||
| work_response(), and the host MUST guarantee that it will be eventually | ||
| passed to work_response() if this function returns LV2_WORKER_SUCCESS. | ||
| */ | ||
| typedef LV2_Worker_Status (*LV2_Worker_Respond_Function)( | ||
| LV2_Worker_Respond_Handle handle, | ||
| uint32_t size, | ||
| const void* data); | ||
|
|
||
| /** | ||
| Plugin Worker Interface. | ||
| This is the interface provided by the plugin to implement a worker method. | ||
| The plugin's extension_data() method should return an LV2_Worker_Interface | ||
| when called with LV2_WORKER__interface as its argument. | ||
| */ | ||
| typedef struct _LV2_Worker_Interface { | ||
| /** | ||
| The worker method. This is called by the host in a non-realtime context | ||
| as requested, possibly with an arbitrary message to handle. | ||
| A response can be sent to run() using `respond`. The plugin MUST NOT | ||
| make any assumptions about which thread calls this method, except that | ||
| there are no real-time requirements and only one call may be executed at | ||
| a time. That is, the host MAY call this method from any non-real-time | ||
| thread, but MUST NOT make concurrent calls to this method from several | ||
| threads. | ||
| @param instance The LV2 instance this is a method on. | ||
| @param respond A function for sending a response to run(). | ||
| @param handle Must be passed to `respond` if it is called. | ||
| @param size The size of `data`. | ||
| @param data Data from run(), or NULL. | ||
| */ | ||
| LV2_Worker_Status (*work)(LV2_Handle instance, | ||
| LV2_Worker_Respond_Function respond, | ||
| LV2_Worker_Respond_Handle handle, | ||
| uint32_t size, | ||
| const void* data); | ||
|
|
||
| /** | ||
| Handle a response from the worker. This is called by the host in the | ||
| run() context when a response from the worker is ready. | ||
| @param instance The LV2 instance this is a method on. | ||
| @param size The size of `body`. | ||
| @param body Message body, or NULL. | ||
| */ | ||
| LV2_Worker_Status (*work_response)(LV2_Handle instance, | ||
| uint32_t size, | ||
| const void* body); | ||
|
|
||
| /** | ||
| Called when all responses for this cycle have been delivered. | ||
| Since work_response() may be called after run() finished, this provides | ||
| a hook for code that must run after the cycle is completed. | ||
| This field may be NULL if the plugin has no use for it. Otherwise, the | ||
| host MUST call it after every run(), regardless of whether or not any | ||
| responses were sent that cycle. | ||
| */ | ||
| LV2_Worker_Status (*end_run)(LV2_Handle instance); | ||
| } LV2_Worker_Interface; | ||
|
|
||
| /** Opaque handle for LV2_Worker_Schedule. */ | ||
| typedef void* LV2_Worker_Schedule_Handle; | ||
|
|
||
| /** | ||
| Schedule Worker Host Feature. | ||
| The host passes this feature to provide a schedule_work() function, which | ||
| the plugin can use to schedule a worker call from run(). | ||
| */ | ||
| typedef struct _LV2_Worker_Schedule { | ||
| /** | ||
| Opaque host data. | ||
| */ | ||
| LV2_Worker_Schedule_Handle handle; | ||
|
|
||
| /** | ||
| Request from run() that the host call the worker. | ||
| This function is in the audio threading class. It should be called from | ||
| run() to request that the host call the work() method in a non-realtime | ||
| context with the given arguments. | ||
| This function is always safe to call from run(), but it is not | ||
| guaranteed that the worker is actually called from a different thread. | ||
| In particular, when free-wheeling (e.g. for offline rendering), the | ||
| worker may be executed immediately. This allows single-threaded | ||
| processing with sample accuracy and avoids timing problems when run() is | ||
| executing much faster or slower than real-time. | ||
| Plugins SHOULD be written in such a way that if the worker runs | ||
| immediately, and responses from the worker are delivered immediately, | ||
| the effect of the work takes place immediately with sample accuracy. | ||
| The `data` MUST be safe for the host to copy and later pass to work(), | ||
| and the host MUST guarantee that it will be eventually passed to work() | ||
| if this function returns LV2_WORKER_SUCCESS. | ||
| @param handle The handle field of this struct. | ||
| @param size The size of `data`. | ||
| @param data Message to pass to work(), or NULL. | ||
| */ | ||
| LV2_Worker_Status (*schedule_work)(LV2_Worker_Schedule_Handle handle, | ||
| uint32_t size, | ||
| const void* data); | ||
| } LV2_Worker_Schedule; | ||
|
|
||
| #ifdef __cplusplus | ||
| } /* extern "C" */ | ||
| #endif | ||
|
|
||
| #endif /* LV2_WORKER_H */ | ||
|
|
||
| /** | ||
| @} | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /* | ||
| Copyright 2012 David Robillard <http://drobilla.net> | ||
| 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. | ||
| */ | ||
|
|
||
| /** | ||
| @defgroup units Units | ||
| Units for LV2 values, see <http://lv2plug.in/ns/extensions/units> for | ||
| details. | ||
| @{ | ||
| */ | ||
|
|
||
| #ifndef LV2_UNITS_H | ||
| #define LV2_UNITS_H | ||
|
|
||
| #define LV2_UNITS_URI "http://lv2plug.in/ns/extensions/units" | ||
| #define LV2_UNITS_PREFIX LV2_UNITS_URI "#" | ||
|
|
||
| #define LV2_UNITS__Conversion LV2_UNITS_PREFIX "Conversion" | ||
| #define LV2_UNITS__Unit LV2_UNITS_PREFIX "Unit" | ||
| #define LV2_UNITS__bar LV2_UNITS_PREFIX "bar" | ||
| #define LV2_UNITS__beat LV2_UNITS_PREFIX "beat" | ||
| #define LV2_UNITS__bpm LV2_UNITS_PREFIX "bpm" | ||
| #define LV2_UNITS__cent LV2_UNITS_PREFIX "cent" | ||
| #define LV2_UNITS__cm LV2_UNITS_PREFIX "cm" | ||
| #define LV2_UNITS__coef LV2_UNITS_PREFIX "coef" | ||
| #define LV2_UNITS__conversion LV2_UNITS_PREFIX "conversion" | ||
| #define LV2_UNITS__db LV2_UNITS_PREFIX "db" | ||
| #define LV2_UNITS__degree LV2_UNITS_PREFIX "degree" | ||
| #define LV2_UNITS__frame LV2_UNITS_PREFIX "frame" | ||
| #define LV2_UNITS__hz LV2_UNITS_PREFIX "hz" | ||
| #define LV2_UNITS__inch LV2_UNITS_PREFIX "inch" | ||
| #define LV2_UNITS__khz LV2_UNITS_PREFIX "khz" | ||
| #define LV2_UNITS__km LV2_UNITS_PREFIX "km" | ||
| #define LV2_UNITS__m LV2_UNITS_PREFIX "m" | ||
| #define LV2_UNITS__mhz LV2_UNITS_PREFIX "mhz" | ||
| #define LV2_UNITS__midiNote LV2_UNITS_PREFIX "midiNote" | ||
| #define LV2_UNITS__mile LV2_UNITS_PREFIX "mile" | ||
| #define LV2_UNITS__min LV2_UNITS_PREFIX "min" | ||
| #define LV2_UNITS__mm LV2_UNITS_PREFIX "mm" | ||
| #define LV2_UNITS__ms LV2_UNITS_PREFIX "ms" | ||
| #define LV2_UNITS__name LV2_UNITS_PREFIX "name" | ||
| #define LV2_UNITS__oct LV2_UNITS_PREFIX "oct" | ||
| #define LV2_UNITS__pc LV2_UNITS_PREFIX "pc" | ||
| #define LV2_UNITS__prefixConversion LV2_UNITS_PREFIX "prefixConversion" | ||
| #define LV2_UNITS__render LV2_UNITS_PREFIX "render" | ||
| #define LV2_UNITS__s LV2_UNITS_PREFIX "s" | ||
| #define LV2_UNITS__semitone12TET LV2_UNITS_PREFIX "semitone12TET" | ||
| #define LV2_UNITS__symbol LV2_UNITS_PREFIX "symbol" | ||
| #define LV2_UNITS__unit LV2_UNITS_PREFIX "unit" | ||
|
|
||
| #endif /* LV2_UNITS_H */ | ||
|
|
||
| /** | ||
| @} | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /* | ||
| Copyright 2016 David Robillard <http://drobilla.net> | ||
| 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. | ||
| */ | ||
|
|
||
| /** | ||
| @defgroup util Utilities | ||
| @ingroup lv2core | ||
| @{ | ||
| */ | ||
|
|
||
| #include <string.h> | ||
|
|
||
| #include "lv2/lv2plug.in/ns/lv2core/lv2.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #else | ||
| # include <stdbool.h> | ||
| #endif | ||
|
|
||
| /** | ||
| Return the data for a feature in a features array. | ||
| If the feature is not found, NULL is returned. Note that this function is | ||
| only useful for features with data, and can not detect features that are | ||
| present but have NULL data. | ||
| */ | ||
| static inline void* | ||
| lv2_features_data(const LV2_Feature*const* features, | ||
| const char* const uri) | ||
| { | ||
| for (const LV2_Feature*const* f = features; *f; ++f) { | ||
| if (!strcmp(uri, (*f)->URI)) { | ||
| return (*f)->data; | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| /** | ||
| Query a features array. | ||
| This function allows getting several features in one call, and detect | ||
| missing required features, with the same caveat of lv2_features_data(). | ||
| The arguments should be a series of const char* uri, void** data, bool | ||
| required, terminated by a NULL URI. The data pointers MUST be initialized | ||
| to NULL. For example: | ||
| @code | ||
| LV2_URID_Log* log = NULL; | ||
| LV2_URID_Map* map = NULL; | ||
| const char* missing = lv2_features_query( | ||
| features, | ||
| LV2_LOG__log, &log, false, | ||
| LV2_URID__map, &map, true, | ||
| NULL); | ||
| @endcode | ||
| @return NULL on success, otherwise the URI of this missing feature. | ||
| */ | ||
| static inline const char* | ||
| lv2_features_query(const LV2_Feature* const* features, ...) | ||
| { | ||
| va_list args; | ||
| va_start(args, features); | ||
|
|
||
| const char* uri = NULL; | ||
| while ((uri = va_arg(args, const char*))) { | ||
| void** data = va_arg(args, void**); | ||
| bool required = va_arg(args, int); | ||
|
|
||
| *data = lv2_features_data(features, uri); | ||
| if (required && !*data) { | ||
| return uri; | ||
| } | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| #ifdef __cplusplus | ||
| } /* extern "C" */ | ||
| #endif | ||
|
|
||
| /** | ||
| @} | ||
| @} | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| #ifndef _SERD_CONFIG_H_ | ||
| #define _SERD_CONFIG_H_ | ||
|
|
||
| #define SERD_INTERNAL | ||
|
|
||
| #define HAVE_FILENO 1 | ||
| #define SERD_VERSION "0.23.0" | ||
|
|
||
| #if defined(__APPLE__) || defined(__WIN32__) | ||
|
|
||
| #elif defined(__HAIKU__) | ||
| # define HAVE_POSIX_MEMALIGN 1 | ||
| #else | ||
| # define HAVE_POSIX_MEMALIGN 1 | ||
| # define HAVE_POSIX_FADVISE 1 | ||
| #endif | ||
|
|
||
| #endif /* _SERD_CONFIG_H_ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| #ifndef _SORD_CONFIG_H_ | ||
| #define _SORD_CONFIG_H_ | ||
|
|
||
| #define SORD_INTERNAL | ||
|
|
||
| #define HAVE_FILENO 1 | ||
| #define SERD_VERSION "0.23.0" | ||
| #define HAVE_SERD 1 | ||
| #define SORD_VERSION "0.15.1" | ||
|
|
||
| #if defined(__APPLE__) || defined(__WIN32__) | ||
|
|
||
| #elif defined(__HAIKU__) | ||
| # define HAVE_POSIX_MEMALIGN 1 | ||
| #else | ||
| # define HAVE_POSIX_MEMALIGN 1 | ||
| # define HAVE_POSIX_FADVISE 1 | ||
| #endif | ||
|
|
||
| #endif /* _SORD_CONFIG_H_ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,228 @@ | ||
| /* | ||
| Copyright 2012-2016 David Robillard <http://drobilla.net> | ||
| 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 sratom.h API for Sratom, an LV2 Atom RDF serialisation library. | ||
| */ | ||
|
|
||
| #ifndef SRATOM_SRATOM_H | ||
| #define SRATOM_SRATOM_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #include "lv2/lv2plug.in/ns/ext/urid/urid.h" | ||
| #include "lv2/lv2plug.in/ns/ext/atom/atom.h" | ||
| #include "lv2/lv2plug.in/ns/ext/atom/forge.h" | ||
| #include "serd/serd.h" | ||
| #include "sord/sord.h" | ||
|
|
||
| #ifdef SRATOM_SHARED | ||
| # ifdef _WIN32 | ||
| # define SRATOM_LIB_IMPORT __declspec(dllimport) | ||
| # define SRATOM_LIB_EXPORT __declspec(dllexport) | ||
| # else | ||
| # define SRATOM_LIB_IMPORT __attribute__((visibility("default"))) | ||
| # define SRATOM_LIB_EXPORT __attribute__((visibility("default"))) | ||
| # endif | ||
| # ifdef SRATOM_INTERNAL | ||
| # define SRATOM_API SRATOM_LIB_EXPORT | ||
| # else | ||
| # define SRATOM_API SRATOM_LIB_IMPORT | ||
| # endif | ||
| #else | ||
| # define SRATOM_API | ||
| #endif | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| /** | ||
| @defgroup sratom Sratom | ||
| An LV2 Atom RDF serialisation library. | ||
| @{ | ||
| */ | ||
|
|
||
| /** | ||
| Atom serialiser. | ||
| */ | ||
| typedef struct SratomImpl Sratom; | ||
|
|
||
| /** | ||
| Mode for reading resources to LV2 Objects. | ||
| This affects how resources (which are either blank nodes or have URIs) are | ||
| read by sratom_read(), since they may be read as simple references (a URI or | ||
| blank node ID) or a complete description (an atom "Object"). | ||
| Currently, blank nodes are always read as Objects, but support for reading | ||
| blank node IDs may be added in the future. | ||
| */ | ||
| typedef enum { | ||
| /** | ||
| Read blank nodes as Objects, and named resources as URIs. | ||
| */ | ||
| SRATOM_OBJECT_MODE_BLANK, | ||
|
|
||
| /** | ||
| Read blank nodes and the main subject as Objects, and any other named | ||
| resources as URIs. The "main subject" is the subject parameter passed | ||
| to sratom_read(); if this is a resource it will be read as an Object, | ||
| but all other named resources encountered will be read as URIs. | ||
| */ | ||
| SRATOM_OBJECT_MODE_BLANK_SUBJECT | ||
| } SratomObjectMode; | ||
|
|
||
| /** | ||
| Create a new Atom serialiser. | ||
| */ | ||
| SRATOM_API | ||
| Sratom* | ||
| sratom_new(LV2_URID_Map* map); | ||
|
|
||
| /** | ||
| Free an Atom serialisation. | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_free(Sratom* sratom); | ||
|
|
||
| /** | ||
| Set the environment for reading or writing Turtle. | ||
| This can be used to set namespace prefixes and a base URI for | ||
| sratom_to_turtle() and sratom_from_turtle(). | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_set_env(Sratom* sratom, | ||
| SerdEnv* env); | ||
|
|
||
| /** | ||
| Set the sink(s) where sratom will write its output. | ||
| This must be called before calling sratom_write(). | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_set_sink(Sratom* sratom, | ||
| const char* base_uri, | ||
| SerdStatementSink sink, | ||
| SerdEndSink end_sink, | ||
| void* handle); | ||
|
|
||
| /** | ||
| Write pretty numeric literals. | ||
| If `pretty_numbers` is true, numbers will be written as pretty Turtle | ||
| literals, rather than string literals with precise types. The cost of this | ||
| is that the types might get fudged on a round-trip to RDF and back. | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_set_pretty_numbers(Sratom* sratom, | ||
| bool pretty_numbers); | ||
|
|
||
| /** | ||
| Configure how resources will be read to form LV2 Objects. | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_set_object_mode(Sratom* sratom, | ||
| SratomObjectMode object_mode); | ||
|
|
||
| /** | ||
| Write an Atom to RDF. | ||
| The serialised atom is written to the sink set by sratom_set_sink(). | ||
| @return 0 on success, or a non-zero error code otherwise. | ||
| */ | ||
| SRATOM_API | ||
| int | ||
| sratom_write(Sratom* sratom, | ||
| LV2_URID_Unmap* unmap, | ||
| uint32_t flags, | ||
| const SerdNode* subject, | ||
| const SerdNode* predicate, | ||
| uint32_t type, | ||
| uint32_t size, | ||
| const void* body); | ||
|
|
||
| /** | ||
| Read an Atom from RDF. | ||
| The resulting atom will be written to `forge`. | ||
| */ | ||
| SRATOM_API | ||
| void | ||
| sratom_read(Sratom* sratom, | ||
| LV2_Atom_Forge* forge, | ||
| SordWorld* world, | ||
| SordModel* model, | ||
| const SordNode* subject); | ||
|
|
||
| /** | ||
| Serialise an Atom to a Turtle string. | ||
| The returned string must be free()'d by the caller. | ||
| */ | ||
| 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); | ||
|
|
||
| /** | ||
| Read an Atom from a Turtle string. | ||
| The returned atom must be free()'d by the caller. | ||
| */ | ||
| SRATOM_API | ||
| LV2_Atom* | ||
| sratom_from_turtle(Sratom* sratom, | ||
| const char* base_uri, | ||
| const SerdNode* subject, | ||
| const SerdNode* predicate, | ||
| const char* str); | ||
|
|
||
| /** | ||
| A convenient resizing sink for LV2_Atom_Forge. | ||
| The handle must point to an initialized SerdChunk. | ||
| */ | ||
| SRATOM_API | ||
| LV2_Atom_Forge_Ref | ||
| sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle, | ||
| const void* buf, | ||
| uint32_t size); | ||
|
|
||
| /** | ||
| The corresponding deref function for sratom_forge_sink. | ||
| */ | ||
| SRATOM_API | ||
| LV2_Atom* | ||
| sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, | ||
| LV2_Atom_Forge_Ref ref); | ||
|
|
||
| /** | ||
| @} | ||
| */ | ||
|
|
||
| #ifdef __cplusplus | ||
| } /* extern "C" */ | ||
| #endif | ||
|
|
||
| #endif /* SRATOM_SRATOM_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,336 @@ | ||
| /* | ||
| * IMPORTANT: The author of lv2vst has no connection with the | ||
| * author of the VeSTige VST-compatibility header, has had no | ||
| * involvement in its creation. | ||
| * | ||
| * The VeSTige header is included in this package in the good-faith | ||
| * belief that it has been cleanly and legally reverse engineered | ||
| * without reference to the official VST SDK and without its | ||
| * developer(s) having agreed to the VST SDK license agreement. | ||
| */ | ||
|
|
||
| /* | ||
| * simple header to allow VeSTige compilation and eventually work | ||
| * | ||
| * Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> | ||
| * | ||
| * This program is free software; you can redistribute it and/or | ||
| * modify it under the terms of the GNU General Public | ||
| * License as published by the Free Software Foundation; either | ||
| * version 2 of the License, or (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| * General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public | ||
| * License along with this program (see COPYING); if not, write to the | ||
| * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| * Boston, MA 02110-1301 USA. | ||
| * | ||
| */ | ||
| #include <stdint.h> | ||
| #ifndef _VESTIGE_H | ||
| #define _VESTIGE_H | ||
|
|
||
| #define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \ | ||
| ( ( (int) b ) << 16 ) | \ | ||
| ( ( (int) c ) << 8 ) | \ | ||
| ( ( (int) d ) << 0 ) ) | ||
|
|
||
| #define audioMasterAutomate 0 | ||
| #define audioMasterVersion 1 | ||
| #define audioMasterCurrentId 2 | ||
| #define audioMasterIdle 3 | ||
| #define audioMasterPinConnected 4 | ||
| // unsupported? 5 | ||
| #define audioMasterWantMidi 6 | ||
| #define audioMasterGetTime 7 | ||
| #define audioMasterProcessEvents 8 | ||
| #define audioMasterSetTime 9 | ||
| #define audioMasterTempoAt 10 | ||
| #define audioMasterGetNumAutomatableParameters 11 | ||
| #define audioMasterGetParameterQuantization 12 | ||
| #define audioMasterIOChanged 13 | ||
| #define audioMasterNeedIdle 14 | ||
| #define audioMasterSizeWindow 15 | ||
| #define audioMasterGetSampleRate 16 | ||
| #define audioMasterGetBlockSize 17 | ||
| #define audioMasterGetInputLatency 18 | ||
| #define audioMasterGetOutputLatency 19 | ||
| #define audioMasterGetPreviousPlug 20 | ||
| #define audioMasterGetNextPlug 21 | ||
| #define audioMasterWillReplaceOrAccumulate 22 | ||
| #define audioMasterGetCurrentProcessLevel 23 | ||
| #define audioMasterGetAutomationState 24 | ||
| #define audioMasterOfflineStart 25 | ||
| #define audioMasterOfflineRead 26 | ||
| #define audioMasterOfflineWrite 27 | ||
| #define audioMasterOfflineGetCurrentPass 28 | ||
| #define audioMasterOfflineGetCurrentMetaPass 29 | ||
| #define audioMasterSetOutputSampleRate 30 | ||
| // unsupported? 31 | ||
| #define audioMasterGetSpeakerArrangement 31 // deprecated in 2.4? | ||
| #define audioMasterGetVendorString 32 | ||
| #define audioMasterGetProductString 33 | ||
| #define audioMasterGetVendorVersion 34 | ||
| #define audioMasterVendorSpecific 35 | ||
| #define audioMasterSetIcon 36 | ||
| #define audioMasterCanDo 37 | ||
| #define audioMasterGetLanguage 38 | ||
| #define audioMasterOpenWindow 39 | ||
| #define audioMasterCloseWindow 40 | ||
| #define audioMasterGetDirectory 41 | ||
| #define audioMasterUpdateDisplay 42 | ||
| #define audioMasterBeginEdit 43 | ||
| #define audioMasterEndEdit 44 | ||
| #define audioMasterOpenFileSelector 45 | ||
| #define audioMasterCloseFileSelector 46 // currently unused | ||
| #define audioMasterEditFile 47 // currently unused | ||
| #define audioMasterGetChunkFile 48 // currently unused | ||
| #define audioMasterGetInputSpeakerArrangement 49 // currently unused | ||
|
|
||
| #define effFlagsHasEditor 1 | ||
| #define effFlagsCanReplacing (1 << 4) // very likely | ||
| #define effFlagsIsSynth (1 << 8) // currently unused | ||
|
|
||
| #define effOpen 0 | ||
| #define effClose 1 | ||
| #define effSetProgram 2 | ||
| #define effGetProgram 3 | ||
| #define effGetProgramName 5 | ||
| #define effGetParamName 8 | ||
| #define effSetSampleRate 10 | ||
| #define effSetBlockSize 11 | ||
| #define effMainsChanged 12 | ||
| #define effEditGetRect 13 | ||
| #define effEditOpen 14 | ||
| #define effEditClose 15 | ||
| #define effEditIdle 19 | ||
| #define effEditTop 20 | ||
| #define effProcessEvents 25 | ||
| #define effGetPlugCategory 35 | ||
| #define effGetEffectName 45 | ||
| #define effGetVendorString 47 | ||
| #define effGetProductString 48 | ||
| #define effGetVendorVersion 49 | ||
| #define effCanDo 51 | ||
| #define effIdle 53 | ||
| #define effGetParameterProperties 56 | ||
| #define effGetVstVersion 58 | ||
| #define effShellGetNextPlugin 70 | ||
| #define effStartProcess 71 | ||
| #define effStopProcess 72 | ||
|
|
||
| #define effBeginSetProgram 67 | ||
| #define effEndSetProgram 68 | ||
|
|
||
| #ifdef WORDS_BIGENDIAN | ||
| // "VstP" | ||
| #define kEffectMagic 0x50747356 | ||
| #else | ||
| // "PtsV" | ||
| #define kEffectMagic 0x56737450 | ||
| #endif | ||
|
|
||
| #define kVstLangEnglish 1 | ||
| #define kVstMidiType 1 | ||
|
|
||
| struct RemoteVstPlugin; | ||
|
|
||
| #define kVstTransportChanged 1 | ||
| #define kVstTransportPlaying (1 << 1) | ||
| #define kVstTransportCycleActive (1 << 2) | ||
| #define kVstTransportRecording (1 << 3) | ||
|
|
||
| #define kVstAutomationWriting (1 << 6) | ||
| #define kVstAutomationReading (1 << 7) | ||
|
|
||
| #define kVstNanosValid (1 << 8) | ||
| #define kVstPpqPosValid (1 << 9) | ||
| #define kVstTempoValid (1 << 10) | ||
| #define kVstBarsValid (1 << 11) | ||
| #define kVstCyclePosValid (1 << 12) | ||
| #define kVstTimeSigValid (1 << 13) | ||
| #define kVstSmpteValid (1 << 14) | ||
| #define kVstClockValid (1 << 15) | ||
|
|
||
| struct _VstMidiEvent | ||
| { | ||
| // 00 | ||
| int type; | ||
| // 04 | ||
| int byteSize; | ||
| // 08 | ||
| int deltaFrames; | ||
| // 0c? | ||
| int flags; | ||
| // 10? | ||
| int noteLength; | ||
| // 14? | ||
| int noteOffset; | ||
| // 18 | ||
| char midiData[4]; | ||
| // 1c? | ||
| char detune; | ||
| // 1d? | ||
| char noteOffVelocity; | ||
| // 1e? | ||
| char reserved1; | ||
| // 1f? | ||
| char reserved2; | ||
| }; | ||
|
|
||
| typedef struct _VstMidiEvent VstMidiEvent; | ||
|
|
||
|
|
||
| struct _VstEvent | ||
| { | ||
| char dump[sizeof (VstMidiEvent)]; | ||
|
|
||
| }; | ||
|
|
||
| typedef struct _VstEvent VstEvent; | ||
|
|
||
| struct _VstEvents | ||
| { | ||
| // 00 | ||
| int numEvents; | ||
| // 04 | ||
| void *reserved; | ||
| // 08 | ||
| VstEvent * events[2]; | ||
| }; | ||
|
|
||
| enum Vestige2StringConstants | ||
| { | ||
| VestigeMaxNameLen = 64, | ||
| VestigeMaxLabelLen = 64, | ||
| VestigeMaxShortLabelLen = 8, | ||
| VestigeMaxCategLabelLen = 24, | ||
| VestigeMaxFileNameLen = 100 | ||
| }; | ||
|
|
||
|
|
||
| enum VstPlugCategory | ||
| { | ||
| kPlugCategUnknown = 0, | ||
| kPlugCategEffect, | ||
| kPlugCategSynth, | ||
| kPlugCategAnalysis, | ||
| kPlugCategMastering, | ||
| kPlugCategSpacializer, | ||
| kPlugCategRoomFx, | ||
| kPlugSurroundFx, | ||
| kPlugCategRestoration, | ||
| kPlugCategOfflineProcess, | ||
| kPlugCategShell, | ||
| kPlugCategGenerator, | ||
| kPlugCategMaxCount | ||
| }; | ||
|
|
||
| typedef struct _VstEvents VstEvents; | ||
|
|
||
| struct _VstParameterProperties | ||
| { | ||
| float stepFloat; /* float step */ | ||
| float smallStepFloat; /* small float step */ | ||
| float largeStepFloat; /* large float step */ | ||
| char label[VestigeMaxLabelLen]; /* parameter label */ | ||
| int32_t flags; /* @see VstParameterFlags */ | ||
| int32_t minInteger; /* integer minimum */ | ||
| int32_t maxInteger; /* integer maximum */ | ||
| int32_t stepInteger; /* integer step */ | ||
| int32_t largeStepInteger; /* large integer step */ | ||
| char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */ | ||
| int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */ | ||
| int16_t category; /* 0: no category, else group index + 1 */ | ||
| int16_t numParametersInCategory; /* number of parameters in category */ | ||
| int16_t reserved; /* zero */ | ||
| char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */ | ||
| char future[16]; /* reserved for future use */ | ||
| }; | ||
|
|
||
| typedef struct _VstParameterProperties VstParameterProperties; | ||
|
|
||
| enum VstParameterFlags | ||
| { | ||
| kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ | ||
| kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */ | ||
| kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */ | ||
| kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */ | ||
| kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */ | ||
| kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */ | ||
| kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */ | ||
| }; | ||
|
|
||
| struct _AEffect | ||
| { | ||
| // Never use virtual functions!!! | ||
| // 00-03 | ||
| int magic; | ||
| // dispatcher 04-07 | ||
| intptr_t (* dispatcher) (struct _AEffect *, int, int, intptr_t, void *, float); | ||
| // process, quite sure 08-0b | ||
| void (* process) (struct _AEffect *, float **, float **, int); | ||
| // setParameter 0c-0f | ||
| void (* setParameter) (struct _AEffect *, int, float); | ||
| // getParameter 10-13 | ||
| float (* getParameter) (struct _AEffect *, int); | ||
| // programs 14-17 | ||
| int numPrograms; | ||
| // Params 18-1b | ||
| int numParams; | ||
| // Input 1c-1f | ||
| int numInputs; | ||
| // Output 20-23 | ||
| int numOutputs; | ||
| // flags 24-27 | ||
| int flags; | ||
| // Fill somewhere 28-2b | ||
| void *ptr1; | ||
| void *ptr2; | ||
| int initialDelay; | ||
| // Zeroes 30-33 34-37 38-3b | ||
| char empty2[4 + 4]; | ||
| // 1.0f 3c-3f | ||
| float unkown_float; | ||
| // An object? pointer 40-43 | ||
| void *object; | ||
| // Zeroes 44-47 | ||
| void *user; | ||
| // Id 48-4b | ||
| int32_t uniqueID; | ||
| // plugin version 4c-4f | ||
| int32_t version; | ||
| // processReplacing 50-53 | ||
| void (* processReplacing) (struct _AEffect *, float **, float **, int); | ||
| }; | ||
|
|
||
| typedef struct _AEffect AEffect; | ||
|
|
||
| typedef struct _VstTimeInfo | ||
| { | ||
| /* info from online documentation of VST provided by Steinberg */ | ||
|
|
||
| double samplePos; | ||
| double sampleRate; | ||
| double nanoSeconds; | ||
| double ppqPos; | ||
| double tempo; | ||
| double barStartPos; | ||
| double cycleStartPos; | ||
| double cycleEndPos; | ||
| int32_t timeSigNumerator; | ||
| int32_t timeSigDenominator; | ||
| int32_t smpteOffset; | ||
| int32_t smpteFrameRate; | ||
| int32_t samplesToNextClock; | ||
| int32_t flags; | ||
|
|
||
| } VstTimeInfo; | ||
|
|
||
| typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float); | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| /* | ||
| Copyright 2008-2014 David Robillard <http://drobilla.net> | ||
| 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 "lilv_internal.h" | ||
|
|
||
| int | ||
| lilv_ptr_cmp(const void* a, const void* b, void* user_data) | ||
| { | ||
| return (intptr_t)a - (intptr_t)b; | ||
| } | ||
|
|
||
| int | ||
| lilv_resource_node_cmp(const void* a, const void* b, void* user_data) | ||
| { | ||
| const SordNode* an = ((const LilvNode*)a)->node; | ||
| const SordNode* bn = ((const LilvNode*)b)->node; | ||
| return (intptr_t)an - (intptr_t)bn; | ||
| } | ||
|
|
||
| /* Generic collection functions */ | ||
|
|
||
| static inline LilvCollection* | ||
| lilv_collection_new(ZixComparator cmp, ZixDestroyFunc destructor) | ||
| { | ||
| return zix_tree_new(false, cmp, NULL, destructor); | ||
| } | ||
|
|
||
| void | ||
| lilv_collection_free(LilvCollection* coll) | ||
| { | ||
| if (coll) | ||
| zix_tree_free((ZixTree*)coll); | ||
| } | ||
|
|
||
| unsigned | ||
| lilv_collection_size(const LilvCollection* coll) | ||
| { | ||
| return (coll ? zix_tree_size((const ZixTree*)coll) : 0); | ||
| } | ||
|
|
||
| LilvIter* | ||
| lilv_collection_begin(const LilvCollection* collection) | ||
| { | ||
| return collection ? (LilvIter*)zix_tree_begin((ZixTree*)collection) : NULL; | ||
| } | ||
|
|
||
| void* | ||
| lilv_collection_get(const LilvCollection* collection, | ||
| const LilvIter* i) | ||
| { | ||
| return zix_tree_get((const ZixTreeIter*)i); | ||
| } | ||
|
|
||
| /* Constructors */ | ||
|
|
||
| LilvScalePoints* | ||
| lilv_scale_points_new(void) | ||
| { | ||
| return lilv_collection_new(lilv_ptr_cmp, | ||
| (ZixDestroyFunc)lilv_scale_point_free); | ||
| } | ||
|
|
||
| LilvNodes* | ||
| lilv_nodes_new(void) | ||
| { | ||
| return lilv_collection_new(lilv_ptr_cmp, | ||
| (ZixDestroyFunc)lilv_node_free); | ||
| } | ||
|
|
||
| LilvUIs* | ||
| lilv_uis_new(void) | ||
| { | ||
| return lilv_collection_new(lilv_header_compare_by_uri, | ||
| (ZixDestroyFunc)lilv_ui_free); | ||
| } | ||
|
|
||
| LilvPluginClasses* | ||
| lilv_plugin_classes_new(void) | ||
| { | ||
| return lilv_collection_new(lilv_header_compare_by_uri, | ||
| (ZixDestroyFunc)lilv_plugin_class_free); | ||
| } | ||
|
|
||
| /* URI based accessors (for collections of things with URIs) */ | ||
|
|
||
| LILV_API const LilvPluginClass* | ||
| lilv_plugin_classes_get_by_uri(const LilvPluginClasses* coll, | ||
| const LilvNode* uri) | ||
| { | ||
| return (LilvPluginClass*)lilv_collection_get_by_uri( | ||
| (const ZixTree*)coll, uri); | ||
| } | ||
|
|
||
| LILV_API const LilvUI* | ||
| lilv_uis_get_by_uri(const LilvUIs* coll, const LilvNode* uri) | ||
| { | ||
| return (LilvUI*)lilv_collection_get_by_uri((const ZixTree*)coll, uri); | ||
| } | ||
|
|
||
| /* Plugins */ | ||
|
|
||
| LilvPlugins* | ||
| lilv_plugins_new(void) | ||
| { | ||
| return lilv_collection_new(lilv_header_compare_by_uri, NULL); | ||
| } | ||
|
|
||
| LILV_API const LilvPlugin* | ||
| lilv_plugins_get_by_uri(const LilvPlugins* list, const LilvNode* uri) | ||
| { | ||
| return (LilvPlugin*)lilv_collection_get_by_uri((const ZixTree*)list, uri); | ||
| } | ||
|
|
||
| /* Nodes */ | ||
|
|
||
| LILV_API bool | ||
| lilv_nodes_contains(const LilvNodes* list, const LilvNode* value) | ||
| { | ||
| LILV_FOREACH(nodes, i, list) | ||
| if (lilv_node_equals(lilv_nodes_get(list, i), value)) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| LILV_API LilvNodes* | ||
| lilv_nodes_merge(const LilvNodes* a, const LilvNodes* b) | ||
| { | ||
| LilvNodes* result = lilv_nodes_new(); | ||
|
|
||
| LILV_FOREACH(nodes, i, a) | ||
| zix_tree_insert((ZixTree*)result, | ||
| lilv_node_duplicate(lilv_nodes_get(a, i)), | ||
| NULL); | ||
|
|
||
| LILV_FOREACH(nodes, i, b) | ||
| zix_tree_insert((ZixTree*)result, | ||
| lilv_node_duplicate(lilv_nodes_get(b, i)), | ||
| NULL); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| /* Iterator */ | ||
|
|
||
| #define LILV_COLLECTION_IMPL(prefix, CT, ET) \ | ||
| LILV_API \ | ||
| unsigned \ | ||
| prefix##_size(const CT* collection) { \ | ||
| return lilv_collection_size(collection); \ | ||
| } \ | ||
| \ | ||
| LILV_API \ | ||
| LilvIter* \ | ||
| prefix##_begin(const CT* collection) { \ | ||
| return lilv_collection_begin(collection); \ | ||
| } \ | ||
| \ | ||
| LILV_API \ | ||
| const ET* \ | ||
| prefix##_get(const CT* collection, LilvIter* i) { \ | ||
| return (ET*)lilv_collection_get(collection, i); \ | ||
| } \ | ||
| \ | ||
| LILV_API \ | ||
| LilvIter* \ | ||
| prefix##_next(const CT* collection, LilvIter* i) { \ | ||
| return zix_tree_iter_next((ZixTreeIter*)i); \ | ||
| } \ | ||
| \ | ||
| LILV_API \ | ||
| bool \ | ||
| prefix##_is_end(const CT* collection, LilvIter* i) { \ | ||
| return zix_tree_iter_is_end((ZixTreeIter*)i); \ | ||
| } | ||
|
|
||
| LILV_COLLECTION_IMPL(lilv_plugin_classes, LilvPluginClasses, LilvPluginClass) | ||
| LILV_COLLECTION_IMPL(lilv_scale_points, LilvScalePoints, LilvScalePoint) | ||
| LILV_COLLECTION_IMPL(lilv_uis, LilvUIs, LilvUI) | ||
| LILV_COLLECTION_IMPL(lilv_nodes, LilvNodes, LilvNode) | ||
| LILV_COLLECTION_IMPL(lilv_plugins, LilvPlugins, LilvPlugin) | ||
|
|
||
| LILV_API void | ||
| lilv_plugin_classes_free(LilvPluginClasses* collection) { | ||
| lilv_collection_free(collection); | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_scale_points_free(LilvScalePoints* collection) { | ||
| lilv_collection_free(collection); | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_uis_free(LilvUIs* collection) { | ||
| lilv_collection_free(collection); | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_nodes_free(LilvNodes* collection) { | ||
| lilv_collection_free(collection); | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_nodes_get_first(const LilvNodes* collection) { | ||
| return (LilvNode*)lilv_collection_get(collection, | ||
| lilv_collection_begin(collection)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| /* | ||
| Copyright 2007-2016 David Robillard <http://drobilla.net> | ||
| 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 <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| LILV_API LilvInstance* | ||
| lilv_plugin_instantiate(const LilvPlugin* plugin, | ||
| double sample_rate, | ||
| const LV2_Feature*const* features) | ||
| { | ||
| lilv_plugin_load_if_necessary(plugin); | ||
| if (plugin->parse_errors) { | ||
| return NULL; | ||
| } | ||
|
|
||
| LilvInstance* result = NULL; | ||
| const LilvNode* const lib_uri = lilv_plugin_get_library_uri(plugin); | ||
| const LilvNode* const bundle_uri = lilv_plugin_get_bundle_uri(plugin); | ||
| char* const bundle_path = lilv_file_uri_parse( | ||
| lilv_node_as_uri(bundle_uri), NULL); | ||
|
|
||
| LilvLib* lib = lilv_lib_open(plugin->world, lib_uri, bundle_path, features); | ||
| if (!lib) { | ||
| lilv_free(bundle_path); | ||
| return NULL; | ||
| } | ||
|
|
||
| const LV2_Feature** local_features = NULL; | ||
| if (features == NULL) { | ||
| local_features = (const LV2_Feature**)malloc(sizeof(LV2_Feature*)); | ||
| local_features[0] = NULL; | ||
| } | ||
|
|
||
| // Search for plugin by URI | ||
| for (uint32_t i = 0; true; ++i) { | ||
| const LV2_Descriptor* ld = lilv_lib_get_plugin(lib, i); | ||
| if (!ld) { | ||
| LILV_ERRORF("No plugin <%s> in <%s>\n", | ||
| lilv_node_as_uri(lilv_plugin_get_uri(plugin)), | ||
| lilv_node_as_uri(lib_uri)); | ||
| lilv_lib_close(lib); | ||
| break; // return NULL | ||
| } | ||
|
|
||
| if (!strcmp(ld->URI, lilv_node_as_uri(lilv_plugin_get_uri(plugin)))) { | ||
| // Create LilvInstance to return | ||
| result = (LilvInstance*)malloc(sizeof(LilvInstance)); | ||
| result->lv2_descriptor = ld; | ||
| result->lv2_handle = ld->instantiate( | ||
| ld, sample_rate, bundle_path, | ||
| (features) ? features : local_features); | ||
| result->pimpl = lib; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| free(local_features); | ||
| lilv_free(bundle_path); | ||
|
|
||
| if (result) { | ||
| if (result->lv2_handle == NULL) { | ||
| // Failed to instantiate | ||
| free(result); | ||
| return NULL; | ||
| } | ||
|
|
||
| // "Connect" all ports to NULL (catches bugs) | ||
| for (uint32_t i = 0; i < lilv_plugin_get_num_ports(plugin); ++i) { | ||
| result->lv2_descriptor->connect_port(result->lv2_handle, i, NULL); | ||
| } | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_instance_free(LilvInstance* instance) | ||
| { | ||
| if (!instance) | ||
| return; | ||
|
|
||
| instance->lv2_descriptor->cleanup(instance->lv2_handle); | ||
| instance->lv2_descriptor = NULL; | ||
| lilv_lib_close((LilvLib*)instance->pimpl); | ||
| instance->pimpl = NULL; | ||
| free(instance); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| /* | ||
| Copyright 2012-2014 David Robillard <http://drobilla.net> | ||
| 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 "lilv_internal.h" | ||
|
|
||
| LilvLib* | ||
| lilv_lib_open(LilvWorld* world, | ||
| const LilvNode* uri, | ||
| const char* bundle_path, | ||
| const LV2_Feature*const* features) | ||
| { | ||
| ZixTreeIter* i = NULL; | ||
| const LilvLib key = { | ||
| world, (LilvNode*)uri, (char*)bundle_path, NULL, NULL, NULL, 0 | ||
| }; | ||
| if (!zix_tree_find(world->libs, &key, &i)) { | ||
| LilvLib* llib = (LilvLib*)zix_tree_get(i); | ||
| ++llib->refs; | ||
| return llib; | ||
| } | ||
|
|
||
| const char* const lib_uri = lilv_node_as_uri(uri); | ||
| char* const lib_path = lilv_file_uri_parse(lib_uri, NULL); | ||
| if (!lib_path) { | ||
| return NULL; | ||
| } | ||
|
|
||
| dlerror(); | ||
| void* lib = dlopen(lib_path, RTLD_NOW); | ||
| if (!lib) { | ||
| LILV_ERRORF("Failed to open library %s (%s)\n", lib_path, dlerror()); | ||
| lilv_free(lib_path); | ||
| return NULL; | ||
| } | ||
|
|
||
| LV2_Descriptor_Function df = (LV2_Descriptor_Function) | ||
| lilv_dlfunc(lib, "lv2_descriptor"); | ||
|
|
||
| LV2_Lib_Descriptor_Function ldf = (LV2_Lib_Descriptor_Function) | ||
| lilv_dlfunc(lib, "lv2_lib_descriptor"); | ||
|
|
||
| const LV2_Lib_Descriptor* desc = NULL; | ||
| if (ldf) { | ||
| desc = ldf(bundle_path, features); | ||
| if (!desc) { | ||
| LILV_ERRORF("Call to %s:lv2_lib_descriptor failed\n", lib_path); | ||
| lilv_free(lib_path); | ||
| return NULL; | ||
| } | ||
| } else if (!df) { | ||
| LILV_ERRORF("No `lv2_descriptor' or `lv2_lib_descriptor' in %s\n", | ||
| lib_path); | ||
| dlclose(lib); | ||
| lilv_free(lib_path); | ||
| return NULL; | ||
| } | ||
| lilv_free(lib_path); | ||
|
|
||
| LilvLib* llib = (LilvLib*)malloc(sizeof(LilvLib)); | ||
| llib->world = world; | ||
| llib->uri = lilv_node_duplicate(uri); | ||
| llib->bundle_path = lilv_strdup(bundle_path); | ||
| llib->lib = lib; | ||
| llib->lv2_descriptor = df; | ||
| llib->desc = desc; | ||
| llib->refs = 1; | ||
|
|
||
| zix_tree_insert(world->libs, llib, NULL); | ||
| return llib; | ||
| } | ||
|
|
||
| const LV2_Descriptor* | ||
| lilv_lib_get_plugin(LilvLib* lib, uint32_t index) | ||
| { | ||
| if (lib->lv2_descriptor) { | ||
| return lib->lv2_descriptor(index); | ||
| } else if (lib->desc) { | ||
| return lib->desc->get_plugin(lib->desc->handle, index); | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
| void | ||
| lilv_lib_close(LilvLib* lib) | ||
| { | ||
| if (--lib->refs == 0) { | ||
| dlclose(lib->lib); | ||
|
|
||
| ZixTreeIter* i = NULL; | ||
| if (lib->world->libs && !zix_tree_find(lib->world->libs, lib, &i)) { | ||
| zix_tree_remove(lib->world->libs, i); | ||
| } | ||
|
|
||
| lilv_node_free(lib->uri); | ||
| free(lib->bundle_path); | ||
| free(lib); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,393 @@ | ||
| /* | ||
| Copyright 2007-2015 David Robillard <http://drobilla.net> | ||
| 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 <math.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| static void | ||
| lilv_node_set_numerics_from_string(LilvNode* val) | ||
| { | ||
| const char* str = (const char*)sord_node_get_string(val->node); | ||
|
|
||
| switch (val->type) { | ||
| case LILV_VALUE_URI: | ||
| case LILV_VALUE_BLANK: | ||
| case LILV_VALUE_STRING: | ||
| case LILV_VALUE_BLOB: | ||
| break; | ||
| case LILV_VALUE_INT: | ||
| val->val.int_val = strtol(str, NULL, 10); | ||
| break; | ||
| case LILV_VALUE_FLOAT: | ||
| val->val.float_val = serd_strtod(str, NULL); | ||
| break; | ||
| case LILV_VALUE_BOOL: | ||
| val->val.bool_val = !strcmp(str, "true"); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| /** Note that if `type` is numeric or boolean, the returned value is corrupt | ||
| * until lilv_node_set_numerics_from_string is called. It is not | ||
| * automatically called from here to avoid overhead and imprecision when the | ||
| * exact string value is known. | ||
| */ | ||
| LilvNode* | ||
| lilv_node_new(LilvWorld* world, LilvNodeType type, const char* str) | ||
| { | ||
| LilvNode* val = (LilvNode*)malloc(sizeof(LilvNode)); | ||
| val->world = world; | ||
| val->type = type; | ||
|
|
||
| const uint8_t* ustr = (const uint8_t*)str; | ||
| switch (type) { | ||
| case LILV_VALUE_URI: | ||
| val->node = sord_new_uri(world->world, ustr); | ||
| break; | ||
| case LILV_VALUE_BLANK: | ||
| val->node = sord_new_blank(world->world, ustr); | ||
| break; | ||
| case LILV_VALUE_STRING: | ||
| val->node = sord_new_literal(world->world, NULL, ustr, NULL); | ||
| break; | ||
| case LILV_VALUE_INT: | ||
| val->node = sord_new_literal( | ||
| world->world, world->uris.xsd_integer, ustr, NULL); | ||
| break; | ||
| case LILV_VALUE_FLOAT: | ||
| val->node = sord_new_literal( | ||
| world->world, world->uris.xsd_decimal, ustr, NULL); | ||
| break; | ||
| case LILV_VALUE_BOOL: | ||
| val->node = sord_new_literal( | ||
| world->world, world->uris.xsd_boolean, ustr, NULL); | ||
| break; | ||
| case LILV_VALUE_BLOB: | ||
| val->node = sord_new_literal( | ||
| world->world, world->uris.xsd_base64Binary, ustr, NULL); | ||
| break; | ||
| } | ||
|
|
||
| if (!val->node) { | ||
| free(val); | ||
| return NULL; | ||
| } | ||
|
|
||
| return val; | ||
| } | ||
|
|
||
| /** Create a new LilvNode from `node`, or return NULL if impossible */ | ||
| LilvNode* | ||
| lilv_node_new_from_node(LilvWorld* world, const SordNode* node) | ||
| { | ||
| if (!node) { | ||
| return NULL; | ||
| } | ||
|
|
||
| LilvNode* result = NULL; | ||
| SordNode* datatype_uri = NULL; | ||
| LilvNodeType type = LILV_VALUE_STRING; | ||
|
|
||
| switch (sord_node_get_type(node)) { | ||
| case SORD_URI: | ||
| result = (LilvNode*)malloc(sizeof(LilvNode)); | ||
| result->world = (LilvWorld*)world; | ||
| result->type = LILV_VALUE_URI; | ||
| result->node = sord_node_copy(node); | ||
| break; | ||
| case SORD_BLANK: | ||
| result = (LilvNode*)malloc(sizeof(LilvNode)); | ||
| result->world = (LilvWorld*)world; | ||
| result->type = LILV_VALUE_BLANK; | ||
| result->node = sord_node_copy(node); | ||
| break; | ||
| case SORD_LITERAL: | ||
| datatype_uri = sord_node_get_datatype(node); | ||
| if (datatype_uri) { | ||
| if (sord_node_equals(datatype_uri, world->uris.xsd_boolean)) | ||
| type = LILV_VALUE_BOOL; | ||
| else if (sord_node_equals(datatype_uri, world->uris.xsd_decimal) | ||
| || sord_node_equals(datatype_uri, world->uris.xsd_double)) | ||
| type = LILV_VALUE_FLOAT; | ||
| else if (sord_node_equals(datatype_uri, world->uris.xsd_integer)) | ||
| type = LILV_VALUE_INT; | ||
| else if (sord_node_equals(datatype_uri, | ||
| world->uris.xsd_base64Binary)) | ||
| type = LILV_VALUE_BLOB; | ||
| else | ||
| LILV_ERRORF("Unknown datatype `%s'\n", | ||
| sord_node_get_string(datatype_uri)); | ||
| } | ||
| result = lilv_node_new( | ||
| world, type, (const char*)sord_node_get_string(node)); | ||
| lilv_node_set_numerics_from_string(result); | ||
| break; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_uri(LilvWorld* world, const char* uri) | ||
| { | ||
| return lilv_node_new(world, LILV_VALUE_URI, uri); | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_file_uri(LilvWorld* world, const char* host, const char* path) | ||
| { | ||
| char* abs_path = lilv_path_absolute(path); | ||
| SerdNode s = serd_node_new_file_uri( | ||
| (const uint8_t*)abs_path, (const uint8_t*)host, NULL, true); | ||
|
|
||
| LilvNode* ret = lilv_node_new(world, LILV_VALUE_URI, (const char*)s.buf); | ||
| serd_node_free(&s); | ||
| free(abs_path); | ||
| return ret; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_string(LilvWorld* world, const char* str) | ||
| { | ||
| return lilv_node_new(world, LILV_VALUE_STRING, str); | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_int(LilvWorld* world, int val) | ||
| { | ||
| char str[32]; | ||
| snprintf(str, sizeof(str), "%d", val); | ||
| LilvNode* ret = lilv_node_new(world, LILV_VALUE_INT, str); | ||
| ret->val.int_val = val; | ||
| return ret; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_float(LilvWorld* world, float val) | ||
| { | ||
| char str[32]; | ||
| snprintf(str, sizeof(str), "%f", val); | ||
| LilvNode* ret = lilv_node_new(world, LILV_VALUE_FLOAT, str); | ||
| ret->val.float_val = val; | ||
| return ret; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_new_bool(LilvWorld* world, bool val) | ||
| { | ||
| LilvNode* ret = lilv_node_new(world, LILV_VALUE_BOOL, | ||
| val ? "true" : "false"); | ||
| ret->val.bool_val = val; | ||
| return ret; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_node_duplicate(const LilvNode* val) | ||
| { | ||
| if (!val) { | ||
| return NULL; | ||
| } | ||
|
|
||
| LilvNode* result = (LilvNode*)malloc(sizeof(LilvNode)); | ||
| result->world = val->world; | ||
| result->node = sord_node_copy(val->node); | ||
| result->val = val->val; | ||
| result->type = val->type; | ||
| return result; | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_node_free(LilvNode* val) | ||
| { | ||
| if (val) { | ||
| sord_node_free(val->world->world, val->node); | ||
| free(val); | ||
| } | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_equals(const LilvNode* value, const LilvNode* other) | ||
| { | ||
| if (value == NULL && other == NULL) | ||
| return true; | ||
| else if (value == NULL || other == NULL) | ||
| return false; | ||
| else if (value->type != other->type) | ||
| return false; | ||
|
|
||
| switch (value->type) { | ||
| case LILV_VALUE_URI: | ||
| case LILV_VALUE_BLANK: | ||
| case LILV_VALUE_STRING: | ||
| case LILV_VALUE_BLOB: | ||
| return sord_node_equals(value->node, other->node); | ||
| case LILV_VALUE_INT: | ||
| return (value->val.int_val == other->val.int_val); | ||
| case LILV_VALUE_FLOAT: | ||
| return (value->val.float_val == other->val.float_val); | ||
| case LILV_VALUE_BOOL: | ||
| return (value->val.bool_val == other->val.bool_val); | ||
| } | ||
|
|
||
| return false; /* shouldn't get here */ | ||
| } | ||
|
|
||
| LILV_API char* | ||
| lilv_node_get_turtle_token(const LilvNode* value) | ||
| { | ||
| const char* str = (const char*)sord_node_get_string(value->node); | ||
| size_t len = 0; | ||
| char* result = NULL; | ||
| SerdNode node; | ||
|
|
||
| switch (value->type) { | ||
| case LILV_VALUE_URI: | ||
| len = strlen(str) + 3; | ||
| result = (char*)calloc(len, 1); | ||
| snprintf(result, len, "<%s>", str); | ||
| break; | ||
| case LILV_VALUE_BLANK: | ||
| len = strlen(str) + 3; | ||
| result = (char*)calloc(len, 1); | ||
| snprintf(result, len, "_:%s", str); | ||
| break; | ||
| case LILV_VALUE_STRING: | ||
| case LILV_VALUE_BOOL: | ||
| case LILV_VALUE_BLOB: | ||
| result = lilv_strdup(str); | ||
| break; | ||
| case LILV_VALUE_INT: | ||
| node = serd_node_new_integer(value->val.int_val); | ||
| result = (char*)node.buf; | ||
| break; | ||
| case LILV_VALUE_FLOAT: | ||
| node = serd_node_new_decimal(value->val.float_val, 8); | ||
| result = (char*)node.buf; | ||
| break; | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_uri(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_URI); | ||
| } | ||
|
|
||
| LILV_API const char* | ||
| lilv_node_as_uri(const LilvNode* value) | ||
| { | ||
| return (lilv_node_is_uri(value) | ||
| ? (const char*)sord_node_get_string(value->node) | ||
| : NULL); | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_blank(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_BLANK); | ||
| } | ||
|
|
||
| LILV_API const char* | ||
| lilv_node_as_blank(const LilvNode* value) | ||
| { | ||
| return (lilv_node_is_blank(value) | ||
| ? (const char*)sord_node_get_string(value->node) | ||
| : NULL); | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_literal(const LilvNode* value) | ||
| { | ||
| if (!value) | ||
| return false; | ||
|
|
||
| switch (value->type) { | ||
| case LILV_VALUE_STRING: | ||
| case LILV_VALUE_INT: | ||
| case LILV_VALUE_FLOAT: | ||
| case LILV_VALUE_BLOB: | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_string(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_STRING); | ||
| } | ||
|
|
||
| LILV_API const char* | ||
| lilv_node_as_string(const LilvNode* value) | ||
| { | ||
| return value ? (const char*)sord_node_get_string(value->node) : NULL; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_int(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_INT); | ||
| } | ||
|
|
||
| LILV_API int | ||
| lilv_node_as_int(const LilvNode* value) | ||
| { | ||
| return lilv_node_is_int(value) ? value->val.int_val : 0; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_float(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_FLOAT); | ||
| } | ||
|
|
||
| LILV_API float | ||
| lilv_node_as_float(const LilvNode* value) | ||
| { | ||
| if (lilv_node_is_float(value)) { | ||
| return value->val.float_val; | ||
| } else if (lilv_node_is_int(value)) { | ||
| return (float)value->val.int_val; | ||
| } | ||
| return NAN; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_is_bool(const LilvNode* value) | ||
| { | ||
| return (value && value->type == LILV_VALUE_BOOL); | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_node_as_bool(const LilvNode* value) | ||
| { | ||
| return lilv_node_is_bool(value) ? value->val.bool_val : false; | ||
| } | ||
|
|
||
| LILV_API char* | ||
| lilv_node_get_path(const LilvNode* value, char** hostname) | ||
| { | ||
| if (lilv_node_is_uri(value)) { | ||
| return lilv_file_uri_parse(lilv_node_as_uri(value), hostname); | ||
| } | ||
| return NULL; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* | ||
| Copyright 2007-2015 David Robillard <http://drobilla.net> | ||
| 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 <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| LilvPluginClass* | ||
| lilv_plugin_class_new(LilvWorld* world, | ||
| const SordNode* parent_node, | ||
| const SordNode* uri, | ||
| const char* label) | ||
| { | ||
| LilvPluginClass* pc = (LilvPluginClass*)malloc(sizeof(LilvPluginClass)); | ||
| pc->world = world; | ||
| pc->uri = lilv_node_new_from_node(world, uri); | ||
| pc->label = lilv_node_new(world, LILV_VALUE_STRING, label); | ||
| pc->parent_uri = (parent_node | ||
| ? lilv_node_new_from_node(world, parent_node) | ||
| : NULL); | ||
| return pc; | ||
| } | ||
|
|
||
| void | ||
| lilv_plugin_class_free(LilvPluginClass* plugin_class) | ||
| { | ||
| if (!plugin_class) { | ||
| return; | ||
| } | ||
|
|
||
| lilv_node_free(plugin_class->uri); | ||
| lilv_node_free(plugin_class->parent_uri); | ||
| lilv_node_free(plugin_class->label); | ||
| free(plugin_class); | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_plugin_class_get_parent_uri(const LilvPluginClass* plugin_class) | ||
| { | ||
| return plugin_class->parent_uri ? plugin_class->parent_uri : NULL; | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_plugin_class_get_uri(const LilvPluginClass* plugin_class) | ||
| { | ||
| return plugin_class->uri; | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_plugin_class_get_label(const LilvPluginClass* plugin_class) | ||
| { | ||
| return plugin_class->label; | ||
| } | ||
|
|
||
| LILV_API LilvPluginClasses* | ||
| lilv_plugin_class_get_children(const LilvPluginClass* plugin_class) | ||
| { | ||
| // Returned list doesn't own categories | ||
| LilvPluginClasses* all = plugin_class->world->plugin_classes; | ||
| LilvPluginClasses* result = zix_tree_new(false, lilv_ptr_cmp, NULL, NULL); | ||
|
|
||
| for (ZixTreeIter* i = zix_tree_begin((ZixTree*)all); | ||
| i != zix_tree_end((ZixTree*)all); | ||
| i = zix_tree_iter_next(i)) { | ||
| const LilvPluginClass* c = (LilvPluginClass*)zix_tree_get(i); | ||
| const LilvNode* parent = lilv_plugin_class_get_parent_uri(c); | ||
| if (parent && lilv_node_equals(lilv_plugin_class_get_uri(plugin_class), | ||
| parent)) | ||
| zix_tree_insert((ZixTree*)result, (LilvPluginClass*)c, NULL); | ||
| } | ||
|
|
||
| return result; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,263 @@ | ||
| /* | ||
| Copyright 2007-2014 David Robillard <http://drobilla.net> | ||
| 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 <assert.h> | ||
| #include <limits.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lv2/lv2plug.in/ns/ext/atom/atom.h" | ||
| #include "lv2/lv2plug.in/ns/ext/event/event.h" | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| LilvPort* | ||
| lilv_port_new(LilvWorld* world, | ||
| const SordNode* node, | ||
| uint32_t index, | ||
| const char* symbol) | ||
| { | ||
| LilvPort* port = (LilvPort*)malloc(sizeof(LilvPort)); | ||
| port->node = lilv_node_new_from_node(world, node); | ||
| port->index = index; | ||
| port->symbol = lilv_node_new(world, LILV_VALUE_STRING, symbol); | ||
| port->classes = lilv_nodes_new(); | ||
| return port; | ||
| } | ||
|
|
||
| void | ||
| lilv_port_free(const LilvPlugin* plugin, LilvPort* port) | ||
| { | ||
| if (port) { | ||
| lilv_node_free(port->node); | ||
| lilv_nodes_free(port->classes); | ||
| lilv_node_free(port->symbol); | ||
| free(port); | ||
| } | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_port_is_a(const LilvPlugin* plugin, | ||
| const LilvPort* port, | ||
| const LilvNode* port_class) | ||
| { | ||
| LILV_FOREACH(nodes, i, port->classes) | ||
| if (lilv_node_equals(lilv_nodes_get(port->classes, i), port_class)) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_port_has_property(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| const LilvNode* property) | ||
| { | ||
| return lilv_world_ask_internal(p->world, | ||
| port->node->node, | ||
| p->world->uris.lv2_portProperty, | ||
| property->node); | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_port_supports_event(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| const LilvNode* event) | ||
| { | ||
| const uint8_t* predicates[] = { (const uint8_t*)LV2_EVENT__supportsEvent, | ||
| (const uint8_t*)LV2_ATOM__supports, | ||
| NULL }; | ||
|
|
||
| for (const uint8_t** pred = predicates; *pred; ++pred) { | ||
| if (lilv_world_ask_internal(p->world, | ||
| port->node->node, | ||
| sord_new_uri(p->world->world, *pred), | ||
| event->node)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| static LilvNodes* | ||
| lilv_port_get_value_by_node(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| const SordNode* predicate) | ||
| { | ||
| return lilv_world_find_nodes_internal(p->world, | ||
| port->node->node, | ||
| predicate, | ||
| NULL); | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_port_get_node(const LilvPlugin* plugin, | ||
| const LilvPort* port) | ||
| { | ||
| return port->node; | ||
| } | ||
|
|
||
| LILV_API LilvNodes* | ||
| lilv_port_get_value(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| const LilvNode* predicate) | ||
| { | ||
| if (!lilv_node_is_uri(predicate)) { | ||
| LILV_ERRORF("Predicate `%s' is not a URI\n", | ||
| sord_node_get_string(predicate->node)); | ||
| return NULL; | ||
| } | ||
|
|
||
| return lilv_port_get_value_by_node(p, port, predicate->node); | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_port_get(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| const LilvNode* predicate) | ||
| { | ||
| LilvNodes* values = lilv_port_get_value(p, port, predicate); | ||
|
|
||
| LilvNode* value = lilv_node_duplicate( | ||
| values ? lilv_nodes_get_first(values) : NULL); | ||
|
|
||
| lilv_nodes_free(values); | ||
| return value; | ||
| } | ||
|
|
||
| LILV_API uint32_t | ||
| lilv_port_get_index(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| return port->index; | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_port_get_symbol(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| return port->symbol; | ||
| } | ||
|
|
||
| LILV_API LilvNode* | ||
| lilv_port_get_name(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| LilvNodes* results = lilv_port_get_value_by_node( | ||
| p, port, p->world->uris.lv2_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> port has no (mandatory) doap:name\n", | ||
| lilv_node_as_string(lilv_plugin_get_uri(p))); | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| LILV_API const LilvNodes* | ||
| lilv_port_get_classes(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| return port->classes; | ||
| } | ||
|
|
||
| LILV_API void | ||
| lilv_port_get_range(const LilvPlugin* p, | ||
| const LilvPort* port, | ||
| LilvNode** def, | ||
| LilvNode** min, | ||
| LilvNode** max) | ||
| { | ||
| if (def) { | ||
| LilvNodes* defaults = lilv_port_get_value_by_node( | ||
| p, port, p->world->uris.lv2_default); | ||
| *def = defaults | ||
| ? lilv_node_duplicate(lilv_nodes_get_first(defaults)) | ||
| : NULL; | ||
| lilv_nodes_free(defaults); | ||
| } | ||
| if (min) { | ||
| LilvNodes* minimums = lilv_port_get_value_by_node( | ||
| p, port, p->world->uris.lv2_minimum); | ||
| *min = minimums | ||
| ? lilv_node_duplicate(lilv_nodes_get_first(minimums)) | ||
| : NULL; | ||
| lilv_nodes_free(minimums); | ||
| } | ||
| if (max) { | ||
| LilvNodes* maximums = lilv_port_get_value_by_node( | ||
| p, port, p->world->uris.lv2_maximum); | ||
| *max = maximums | ||
| ? lilv_node_duplicate(lilv_nodes_get_first(maximums)) | ||
| : NULL; | ||
| lilv_nodes_free(maximums); | ||
| } | ||
| } | ||
|
|
||
| LILV_API LilvScalePoints* | ||
| lilv_port_get_scale_points(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| SordIter* points = lilv_world_query_internal( | ||
| p->world, | ||
| port->node->node, | ||
| sord_new_uri(p->world->world, (const uint8_t*)LV2_CORE__scalePoint), | ||
| NULL); | ||
|
|
||
| LilvScalePoints* ret = NULL; | ||
| if (!sord_iter_end(points)) | ||
| ret = lilv_scale_points_new(); | ||
|
|
||
| FOREACH_MATCH(points) { | ||
| const SordNode* point = sord_iter_get_node(points, SORD_OBJECT); | ||
|
|
||
| LilvNode* value = lilv_plugin_get_unique(p, | ||
| point, | ||
| p->world->uris.rdf_value); | ||
|
|
||
| LilvNode* label = lilv_plugin_get_unique(p, | ||
| point, | ||
| p->world->uris.rdfs_label); | ||
|
|
||
| if (value && label) { | ||
| zix_tree_insert( | ||
| (ZixTree*)ret, lilv_scale_point_new(value, label), NULL); | ||
| } | ||
| } | ||
| sord_iter_free(points); | ||
|
|
||
| assert(!ret || lilv_nodes_size(ret) > 0); | ||
| return ret; | ||
| } | ||
|
|
||
| LILV_API LilvNodes* | ||
| lilv_port_get_properties(const LilvPlugin* p, | ||
| const LilvPort* port) | ||
| { | ||
| LilvNode* pred = lilv_node_new_from_node( | ||
| p->world, p->world->uris.lv2_portProperty); | ||
| LilvNodes* ret = lilv_port_get_value(p, port, pred); | ||
| lilv_node_free(pred); | ||
| return ret; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| /* | ||
| Copyright 2007-2015 David Robillard <http://drobilla.net> | ||
| 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 <limits.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| typedef enum { | ||
| LILV_LANG_MATCH_NONE, ///< Language does not match at all | ||
| LILV_LANG_MATCH_PARTIAL, ///< Partial (language, but not country) match | ||
| LILV_LANG_MATCH_EXACT ///< Exact (language and country) match | ||
| } LilvLangMatch; | ||
|
|
||
| static LilvLangMatch | ||
| lilv_lang_matches(const char* a, const char* b) | ||
| { | ||
| if (!strcmp(a, b)) { | ||
| return LILV_LANG_MATCH_EXACT; | ||
| } | ||
|
|
||
| const char* a_dash = strchr(a, '-'); | ||
| const size_t a_lang_len = a_dash ? (size_t)(a_dash - a) : strlen(a); | ||
| const char* b_dash = strchr(b, '-'); | ||
| const size_t b_lang_len = b_dash ? (size_t)(b_dash - b) : strlen(b); | ||
|
|
||
| if (a_lang_len == b_lang_len && !strncmp(a, b, a_lang_len)) { | ||
| return LILV_LANG_MATCH_PARTIAL; | ||
| } | ||
|
|
||
| return LILV_LANG_MATCH_NONE; | ||
| } | ||
|
|
||
| static LilvNodes* | ||
| lilv_nodes_from_stream_objects_i18n(LilvWorld* world, | ||
| SordIter* stream, | ||
| SordQuadIndex field) | ||
| { | ||
| LilvNodes* values = lilv_nodes_new(); | ||
| const SordNode* nolang = NULL; // Untranslated value | ||
| const SordNode* partial = NULL; // Partial language match | ||
| char* syslang = lilv_get_lang(); | ||
| FOREACH_MATCH(stream) { | ||
| const SordNode* value = sord_iter_get_node(stream, field); | ||
| if (sord_node_get_type(value) == SORD_LITERAL) { | ||
| const char* lang = sord_node_get_language(value); | ||
| LilvLangMatch lm = LILV_LANG_MATCH_NONE; | ||
| if (lang) { | ||
| lm = (syslang) | ||
| ? lilv_lang_matches(lang, syslang) | ||
| : LILV_LANG_MATCH_PARTIAL; | ||
| } else { | ||
| nolang = value; | ||
| if (!syslang) { | ||
| lm = LILV_LANG_MATCH_EXACT; | ||
| } | ||
| } | ||
|
|
||
| if (lm == LILV_LANG_MATCH_EXACT) { | ||
| // Exact language match, add to results | ||
| zix_tree_insert((ZixTree*)values, | ||
| lilv_node_new_from_node(world, value), | ||
| NULL); | ||
| } else if (lm == LILV_LANG_MATCH_PARTIAL) { | ||
| // Partial language match, save in case we find no exact | ||
| partial = value; | ||
| } | ||
| } else { | ||
| zix_tree_insert((ZixTree*)values, | ||
| lilv_node_new_from_node(world, value), | ||
| NULL); | ||
| } | ||
| } | ||
| sord_iter_free(stream); | ||
| free(syslang); | ||
|
|
||
| if (lilv_nodes_size(values) > 0) { | ||
| return values; | ||
| } | ||
|
|
||
| const SordNode* best = nolang; | ||
| if (syslang && partial) { | ||
| // Partial language match for system language | ||
| best = partial; | ||
| } else if (!best) { | ||
| // No languages matches at all, and no untranslated value | ||
| // Use any value, if possible | ||
| best = partial; | ||
| } | ||
|
|
||
| if (best) { | ||
| zix_tree_insert( | ||
| (ZixTree*)values, lilv_node_new_from_node(world, best), NULL); | ||
| } else { | ||
| // No matches whatsoever | ||
| lilv_nodes_free(values); | ||
| values = NULL; | ||
| } | ||
|
|
||
| return values; | ||
| } | ||
|
|
||
| LilvNodes* | ||
| lilv_nodes_from_stream_objects(LilvWorld* world, | ||
| SordIter* stream, | ||
| SordQuadIndex field) | ||
| { | ||
| if (sord_iter_end(stream)) { | ||
| sord_iter_free(stream); | ||
| return NULL; | ||
| } else if (world->opt.filter_language) { | ||
| return lilv_nodes_from_stream_objects_i18n(world, stream, field); | ||
| } else { | ||
| LilvNodes* values = lilv_nodes_new(); | ||
| FOREACH_MATCH(stream) { | ||
| const SordNode* value = sord_iter_get_node(stream, field); | ||
| LilvNode* node = lilv_node_new_from_node(world, value); | ||
| if (node) { | ||
| zix_tree_insert((ZixTree*)values, node, NULL); | ||
| } | ||
| } | ||
| sord_iter_free(stream); | ||
| return values; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| Copyright 2007-2014 David Robillard <http://drobilla.net> | ||
| 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 "lilv_internal.h" | ||
|
|
||
| /** Ownership of value and label is taken */ | ||
| LilvScalePoint* | ||
| lilv_scale_point_new(LilvNode* value, LilvNode* label) | ||
| { | ||
| LilvScalePoint* point = (LilvScalePoint*)malloc(sizeof(LilvScalePoint)); | ||
| point->value = value; | ||
| point->label = label; | ||
| return point; | ||
| } | ||
|
|
||
| void | ||
| lilv_scale_point_free(LilvScalePoint* point) | ||
| { | ||
| if (point) { | ||
| lilv_node_free(point->value); | ||
| lilv_node_free(point->label); | ||
| free(point); | ||
| } | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_scale_point_get_value(const LilvScalePoint* p) | ||
| { | ||
| return p->value; | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_scale_point_get_label(const LilvScalePoint* p) | ||
| { | ||
| return p->label; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| /* | ||
| Copyright 2007-2014 David Robillard <http://drobilla.net> | ||
| 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 <assert.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "lilv_internal.h" | ||
|
|
||
| LilvUI* | ||
| lilv_ui_new(LilvWorld* world, | ||
| LilvNode* uri, | ||
| LilvNode* type_uri, | ||
| LilvNode* binary_uri) | ||
| { | ||
| assert(uri); | ||
| assert(type_uri); | ||
| assert(binary_uri); | ||
|
|
||
| LilvUI* ui = (LilvUI*)malloc(sizeof(LilvUI)); | ||
| ui->world = world; | ||
| ui->uri = uri; | ||
| ui->binary_uri = binary_uri; | ||
|
|
||
| // FIXME: kludge | ||
| char* bundle = lilv_strdup(lilv_node_as_string(ui->binary_uri)); | ||
| char* last_slash = strrchr(bundle, '/') + 1; | ||
| *last_slash = '\0'; | ||
| ui->bundle_uri = lilv_new_uri(world, bundle); | ||
| free(bundle); | ||
|
|
||
| ui->classes = lilv_nodes_new(); | ||
| zix_tree_insert((ZixTree*)ui->classes, type_uri, NULL); | ||
|
|
||
| return ui; | ||
| } | ||
|
|
||
| void | ||
| lilv_ui_free(LilvUI* ui) | ||
| { | ||
| lilv_node_free(ui->uri); | ||
| lilv_node_free(ui->bundle_uri); | ||
| lilv_node_free(ui->binary_uri); | ||
| lilv_nodes_free(ui->classes); | ||
| free(ui); | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_ui_get_uri(const LilvUI* ui) | ||
| { | ||
| return ui->uri; | ||
| } | ||
|
|
||
| LILV_API unsigned | ||
| lilv_ui_is_supported(const LilvUI* ui, | ||
| LilvUISupportedFunc supported_func, | ||
| const LilvNode* container_type, | ||
| const LilvNode** ui_type) | ||
| { | ||
| const LilvNodes* classes = lilv_ui_get_classes(ui); | ||
| LILV_FOREACH(nodes, c, classes) { | ||
| const LilvNode* type = lilv_nodes_get(classes, c); | ||
| const unsigned q = supported_func(lilv_node_as_uri(container_type), | ||
| lilv_node_as_uri(type)); | ||
| if (q) { | ||
| if (ui_type) { | ||
| *ui_type = type; | ||
| } | ||
| return q; | ||
| } | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| LILV_API const LilvNodes* | ||
| lilv_ui_get_classes(const LilvUI* ui) | ||
| { | ||
| return ui->classes; | ||
| } | ||
|
|
||
| LILV_API bool | ||
| lilv_ui_is_a(const LilvUI* ui, const LilvNode* ui_class_uri) | ||
| { | ||
| return lilv_nodes_contains(ui->classes, ui_class_uri); | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_ui_get_bundle_uri(const LilvUI* ui) | ||
| { | ||
| return ui->bundle_uri; | ||
| } | ||
|
|
||
| LILV_API const LilvNode* | ||
| lilv_ui_get_binary_uri(const LilvUI* ui) | ||
| { | ||
| return ui->binary_uri; | ||
| } |