105 changes: 105 additions & 0 deletions include/lv2/lv2plug.in/ns/ext/uri-map/uri-map.h
@@ -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 */

/**
@}
*/
137 changes: 137 additions & 0 deletions include/lv2/lv2plug.in/ns/ext/urid/urid.h
@@ -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 */

/**
@}
*/
177 changes: 177 additions & 0 deletions include/lv2/lv2plug.in/ns/ext/worker/worker.h
@@ -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 */

/**
@}
*/
446 changes: 446 additions & 0 deletions include/lv2/lv2plug.in/ns/extensions/ui/ui.h

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions include/lv2/lv2plug.in/ns/extensions/units/units.h
@@ -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 */

/**
@}
*/
474 changes: 474 additions & 0 deletions include/lv2/lv2plug.in/ns/lv2core/lv2.h

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions include/lv2/lv2plug.in/ns/lv2core/lv2_util.h
@@ -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

/**
@}
@}
*/
994 changes: 994 additions & 0 deletions include/serd/serd.h

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions include/serd_config.h
@@ -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_ */
659 changes: 659 additions & 0 deletions include/sord/sord.h

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions include/sord_config.h
@@ -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_ */
228 changes: 228 additions & 0 deletions include/sratom/sratom.h
@@ -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 */
336 changes: 336 additions & 0 deletions include/vestige.h
@@ -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
220 changes: 220 additions & 0 deletions lib/lilv/collections.c
@@ -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));
}
104 changes: 104 additions & 0 deletions lib/lilv/instance.c
@@ -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);
}
111 changes: 111 additions & 0 deletions lib/lilv/lib.c
@@ -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);
}
}
441 changes: 441 additions & 0 deletions lib/lilv/lilv_internal.h

Large diffs are not rendered by default.

393 changes: 393 additions & 0 deletions lib/lilv/node.c
@@ -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;
}
1,129 changes: 1,129 additions & 0 deletions lib/lilv/plugin.c

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions lib/lilv/pluginclass.c
@@ -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;
}
263 changes: 263 additions & 0 deletions lib/lilv/port.c
@@ -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;
}
139 changes: 139 additions & 0 deletions lib/lilv/query.c
@@ -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;
}
}
49 changes: 49 additions & 0 deletions lib/lilv/scalepoint.c
@@ -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;
}
1,322 changes: 1,322 additions & 0 deletions lib/lilv/state.c

Large diffs are not rendered by default.

111 changes: 111 additions & 0 deletions lib/lilv/ui.c
@@ -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;
}