diff options
Diffstat (limited to 'include')
30 files changed, 5635 insertions, 0 deletions
diff --git a/include/lv2/atom/atom.h b/include/lv2/atom/atom.h new file mode 100644 index 0000000..b090c1e --- /dev/null +++ b/include/lv2/atom/atom.h @@ -0,0 +1,260 @@ +/* + Copyright 2008-2016 David Robillard <d@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. +*/ + +#ifndef LV2_ATOM_H +#define LV2_ATOM_H + +/** + @defgroup atom Atom + @ingroup lv2 + + A generic value container and several data types. + + See <http://lv2plug.in/ns/ext/atom> for details. + + @{ +*/ + +#include <stdint.h> + +// clang-format off + +#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom" ///< http://lv2plug.in/ns/ext/atom +#define LV2_ATOM_PREFIX LV2_ATOM_URI "#" ///< http://lv2plug.in/ns/ext/atom# + +#define LV2_ATOM__Atom LV2_ATOM_PREFIX "Atom" ///< http://lv2plug.in/ns/ext/atom#Atom +#define LV2_ATOM__AtomPort LV2_ATOM_PREFIX "AtomPort" ///< http://lv2plug.in/ns/ext/atom#AtomPort +#define LV2_ATOM__Blank LV2_ATOM_PREFIX "Blank" ///< http://lv2plug.in/ns/ext/atom#Blank +#define LV2_ATOM__Bool LV2_ATOM_PREFIX "Bool" ///< http://lv2plug.in/ns/ext/atom#Bool +#define LV2_ATOM__Chunk LV2_ATOM_PREFIX "Chunk" ///< http://lv2plug.in/ns/ext/atom#Chunk +#define LV2_ATOM__Double LV2_ATOM_PREFIX "Double" ///< http://lv2plug.in/ns/ext/atom#Double +#define LV2_ATOM__Event LV2_ATOM_PREFIX "Event" ///< http://lv2plug.in/ns/ext/atom#Event +#define LV2_ATOM__Float LV2_ATOM_PREFIX "Float" ///< http://lv2plug.in/ns/ext/atom#Float +#define LV2_ATOM__Int LV2_ATOM_PREFIX "Int" ///< http://lv2plug.in/ns/ext/atom#Int +#define LV2_ATOM__Literal LV2_ATOM_PREFIX "Literal" ///< http://lv2plug.in/ns/ext/atom#Literal +#define LV2_ATOM__Long LV2_ATOM_PREFIX "Long" ///< http://lv2plug.in/ns/ext/atom#Long +#define LV2_ATOM__Number LV2_ATOM_PREFIX "Number" ///< http://lv2plug.in/ns/ext/atom#Number +#define LV2_ATOM__Object LV2_ATOM_PREFIX "Object" ///< http://lv2plug.in/ns/ext/atom#Object +#define LV2_ATOM__Path LV2_ATOM_PREFIX "Path" ///< http://lv2plug.in/ns/ext/atom#Path +#define LV2_ATOM__Property LV2_ATOM_PREFIX "Property" ///< http://lv2plug.in/ns/ext/atom#Property +#define LV2_ATOM__Resource LV2_ATOM_PREFIX "Resource" ///< http://lv2plug.in/ns/ext/atom#Resource +#define LV2_ATOM__Sequence LV2_ATOM_PREFIX "Sequence" ///< http://lv2plug.in/ns/ext/atom#Sequence +#define LV2_ATOM__Sound LV2_ATOM_PREFIX "Sound" ///< http://lv2plug.in/ns/ext/atom#Sound +#define LV2_ATOM__String LV2_ATOM_PREFIX "String" ///< http://lv2plug.in/ns/ext/atom#String +#define LV2_ATOM__Tuple LV2_ATOM_PREFIX "Tuple" ///< http://lv2plug.in/ns/ext/atom#Tuple +#define LV2_ATOM__URI LV2_ATOM_PREFIX "URI" ///< http://lv2plug.in/ns/ext/atom#URI +#define LV2_ATOM__URID LV2_ATOM_PREFIX "URID" ///< http://lv2plug.in/ns/ext/atom#URID +#define LV2_ATOM__Vector LV2_ATOM_PREFIX "Vector" ///< http://lv2plug.in/ns/ext/atom#Vector +#define LV2_ATOM__atomTransfer LV2_ATOM_PREFIX "atomTransfer" ///< http://lv2plug.in/ns/ext/atom#atomTransfer +#define LV2_ATOM__beatTime LV2_ATOM_PREFIX "beatTime" ///< http://lv2plug.in/ns/ext/atom#beatTime +#define LV2_ATOM__bufferType LV2_ATOM_PREFIX "bufferType" ///< http://lv2plug.in/ns/ext/atom#bufferType +#define LV2_ATOM__childType LV2_ATOM_PREFIX "childType" ///< http://lv2plug.in/ns/ext/atom#childType +#define LV2_ATOM__eventTransfer LV2_ATOM_PREFIX "eventTransfer" ///< http://lv2plug.in/ns/ext/atom#eventTransfer +#define LV2_ATOM__frameTime LV2_ATOM_PREFIX "frameTime" ///< http://lv2plug.in/ns/ext/atom#frameTime +#define LV2_ATOM__supports LV2_ATOM_PREFIX "supports" ///< http://lv2plug.in/ns/ext/atom#supports +#define LV2_ATOM__timeUnit LV2_ATOM_PREFIX "timeUnit" ///< http://lv2plug.in/ns/ext/atom#timeUnit + +// clang-format on + +#define LV2_ATOM_REFERENCE_TYPE 0 ///< The special type for a reference atom + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond */ +/** This expression will fail to compile if double does not fit in 64 bits. */ +typedef char lv2_atom_assert_double_fits_in_64_bits + [((sizeof(double) <= sizeof(uint64_t)) * 2) - 1]; +/** @endcond */ + +/** + Return a pointer to the contents of an Atom. The "contents" of an atom + is the data past the complete type-specific header. + @param type The type of the atom, for example LV2_Atom_String. + @param atom A variable-sized atom. +*/ +#define LV2_ATOM_CONTENTS(type, atom) ((void*)((uint8_t*)(atom) + sizeof(type))) + +/** + Const version of LV2_ATOM_CONTENTS. +*/ +#define LV2_ATOM_CONTENTS_CONST(type, atom) \ + ((const void*)((const uint8_t*)(atom) + sizeof(type))) + +/** + Return a pointer to the body of an Atom. The "body" of an atom is the + data just past the LV2_Atom head (i.e. the same offset for all types). +*/ +#define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom) + +/** + Const version of LV2_ATOM_BODY. +*/ +#define LV2_ATOM_BODY_CONST(atom) LV2_ATOM_CONTENTS_CONST(LV2_Atom, atom) + +/** The header of an atom:Atom. */ +typedef struct { + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t type; /**< Type of this atom (mapped URI). */ +} LV2_Atom; + +/** An atom:Int or atom:Bool. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + int32_t body; /**< Integer value. */ +} LV2_Atom_Int; + +/** An atom:Long. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + int64_t body; /**< Integer value. */ +} LV2_Atom_Long; + +/** An atom:Float. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + float body; /**< Floating point value. */ +} LV2_Atom_Float; + +/** An atom:Double. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + double body; /**< Floating point value. */ +} LV2_Atom_Double; + +/** An atom:Bool. May be cast to LV2_Atom. */ +typedef LV2_Atom_Int LV2_Atom_Bool; + +/** An atom:URID. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + uint32_t body; /**< URID. */ +} LV2_Atom_URID; + +/** An atom:String. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + /* Contents (a null-terminated UTF-8 string) follow here. */ +} LV2_Atom_String; + +/** The body of an atom:Literal. */ +typedef struct { + uint32_t datatype; /**< Datatype URID. */ + uint32_t lang; /**< Language URID. */ + /* Contents (a null-terminated UTF-8 string) follow here. */ +} LV2_Atom_Literal_Body; + +/** An atom:Literal. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Literal_Body body; /**< Body. */ +} LV2_Atom_Literal; + +/** An atom:Tuple. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + /* Contents (a series of complete atoms) follow here. */ +} LV2_Atom_Tuple; + +/** The body of an atom:Vector. */ +typedef struct { + uint32_t child_size; /**< The size of each element in the vector. */ + uint32_t child_type; /**< The type of each element in the vector. */ + /* Contents (a series of packed atom bodies) follow here. */ +} LV2_Atom_Vector_Body; + +/** An atom:Vector. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Vector_Body body; /**< Body. */ +} LV2_Atom_Vector; + +/** The body of an atom:Property (typically in an atom:Object). */ +typedef struct { + uint32_t key; /**< Key (predicate) (mapped URI). */ + uint32_t context; /**< Context URID (may be, and generally is, 0). */ + LV2_Atom value; /**< Value atom header. */ + /* Value atom body follows here. */ +} LV2_Atom_Property_Body; + +/** An atom:Property. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Property_Body body; /**< Body. */ +} LV2_Atom_Property; + +/** The body of an atom:Object. May be cast to LV2_Atom. */ +typedef struct { + uint32_t id; /**< URID, or 0 for blank. */ + uint32_t otype; /**< Type URID (same as rdf:type, for fast dispatch). */ + /* Contents (a series of property bodies) follow here. */ +} LV2_Atom_Object_Body; + +/** An atom:Object. May be cast to LV2_Atom. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Object_Body body; /**< Body. */ +} LV2_Atom_Object; + +/** The header of an atom:Event. Note this type is NOT an LV2_Atom. */ +typedef struct { + /** Time stamp. Which type is valid is determined by context. */ + union { + int64_t frames; /**< Time in audio frames. */ + double beats; /**< Time in beats. */ + } time; + LV2_Atom body; /**< Event body atom header. */ + /* Body atom contents follow here. */ +} LV2_Atom_Event; + +/** + The body of an atom:Sequence (a sequence of events). + + The unit field is either a URID that described an appropriate time stamp + type, or may be 0 where a default stamp type is known. For + LV2_Descriptor::run(), the default stamp type is audio frames. + + The contents of a sequence is a series of LV2_Atom_Event, each aligned + to 64-bits, for example: + <pre> + | Event 1 (size 6) | Event 2 + | | | | | | | | | + | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + |FRAMES |TYPE |SIZE |DATADATADATAPAD|FRAMES |... + </pre> +*/ +typedef struct { + uint32_t unit; /**< URID of unit of event time stamps. */ + uint32_t pad; /**< Currently unused. */ + /* Contents (a series of events) follow here. */ +} LV2_Atom_Sequence_Body; + +/** An atom:Sequence. */ +typedef struct { + LV2_Atom atom; /**< Atom header. */ + LV2_Atom_Sequence_Body body; /**< Body. */ +} LV2_Atom_Sequence; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_ATOM_H */ diff --git a/include/lv2/atom/forge.h b/include/lv2/atom/forge.h new file mode 100644 index 0000000..280bd53 --- /dev/null +++ b/include/lv2/atom/forge.h @@ -0,0 +1,683 @@ +/* + Copyright 2008-2016 David Robillard <d@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 forge.h An API for constructing LV2 atoms. + + This file provides an API for constructing Atoms which makes it relatively + simple to build nested atoms of arbitrary complexity without requiring + dynamic memory allocation. + + The API is based on successively appending the appropriate pieces to build a + complete Atom. The size of containers is automatically updated. Functions + that begin a container return (via their frame argument) a stack frame which + must be popped when the container is finished. + + All output is written to a user-provided buffer or sink function. This + makes it possible to create atoms on the stack, on the heap, in LV2 port + buffers, in a ringbuffer, or elsewhere, all using the same API. + + This entire API is realtime safe if used with a buffer or a realtime safe + sink, except lv2_atom_forge_init() which is only realtime safe if the URI + map function is. + + Note these functions are all static inline, do not take their address. + + This header is non-normative, it is provided for convenience. +*/ + +#ifndef LV2_ATOM_FORGE_H +#define LV2_ATOM_FORGE_H + +/** + @defgroup forge Forge + @ingroup atom + + An API for constructing LV2 atoms. + + @{ +*/ + +#include "lv2/atom/atom.h" +#include "lv2/atom/util.h" +#include "lv2/core/attributes.h" +#include "lv2/urid/urid.h" + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Disable deprecation warnings for Blank and Resource +LV2_DISABLE_DEPRECATION_WARNINGS + +/** Handle for LV2_Atom_Forge_Sink. */ +typedef void* LV2_Atom_Forge_Sink_Handle; + +/** A reference to a chunk of written output. */ +typedef intptr_t LV2_Atom_Forge_Ref; + +/** Sink function for writing output. See lv2_atom_forge_set_sink(). */ +typedef LV2_Atom_Forge_Ref (*LV2_Atom_Forge_Sink)( + LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size); + +/** Function for resolving a reference. See lv2_atom_forge_set_sink(). */ +typedef LV2_Atom* (*LV2_Atom_Forge_Deref_Func)( + LV2_Atom_Forge_Sink_Handle handle, + LV2_Atom_Forge_Ref ref); + +/** A stack frame used for keeping track of nested Atom containers. */ +typedef struct LV2_Atom_Forge_Frame { + struct LV2_Atom_Forge_Frame* parent; + LV2_Atom_Forge_Ref ref; +} LV2_Atom_Forge_Frame; + +/** A "forge" for creating atoms by appending to a buffer. */ +typedef struct { + uint8_t* buf; + uint32_t offset; + uint32_t size; + + LV2_Atom_Forge_Sink sink; + LV2_Atom_Forge_Deref_Func deref; + LV2_Atom_Forge_Sink_Handle handle; + + LV2_Atom_Forge_Frame* stack; + + LV2_URID Blank LV2_DEPRECATED; + LV2_URID Bool; + LV2_URID Chunk; + LV2_URID Double; + LV2_URID Float; + LV2_URID Int; + LV2_URID Long; + LV2_URID Literal; + LV2_URID Object; + LV2_URID Path; + LV2_URID Property; + LV2_URID Resource LV2_DEPRECATED; + LV2_URID Sequence; + LV2_URID String; + LV2_URID Tuple; + LV2_URID URI; + LV2_URID URID; + LV2_URID Vector; +} LV2_Atom_Forge; + +static inline void +lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size); + +/** + Initialise `forge`. + + URIs will be mapped using `map` and stored, a reference to `map` itself is + not held. +*/ +static inline void +lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map) +{ + lv2_atom_forge_set_buffer(forge, NULL, 0); + forge->Blank = map->map(map->handle, LV2_ATOM__Blank); + forge->Bool = map->map(map->handle, LV2_ATOM__Bool); + forge->Chunk = map->map(map->handle, LV2_ATOM__Chunk); + forge->Double = map->map(map->handle, LV2_ATOM__Double); + forge->Float = map->map(map->handle, LV2_ATOM__Float); + forge->Int = map->map(map->handle, LV2_ATOM__Int); + forge->Long = map->map(map->handle, LV2_ATOM__Long); + forge->Literal = map->map(map->handle, LV2_ATOM__Literal); + forge->Object = map->map(map->handle, LV2_ATOM__Object); + forge->Path = map->map(map->handle, LV2_ATOM__Path); + forge->Property = map->map(map->handle, LV2_ATOM__Property); + forge->Resource = map->map(map->handle, LV2_ATOM__Resource); + forge->Sequence = map->map(map->handle, LV2_ATOM__Sequence); + forge->String = map->map(map->handle, LV2_ATOM__String); + forge->Tuple = map->map(map->handle, LV2_ATOM__Tuple); + forge->URI = map->map(map->handle, LV2_ATOM__URI); + forge->URID = map->map(map->handle, LV2_ATOM__URID); + forge->Vector = map->map(map->handle, LV2_ATOM__Vector); +} + +/** Access the Atom pointed to by a reference. */ +static inline LV2_Atom* +lv2_atom_forge_deref(LV2_Atom_Forge* forge, LV2_Atom_Forge_Ref ref) +{ + return forge->buf ? (LV2_Atom*)ref : forge->deref(forge->handle, ref); +} + +/** + @name Object Stack + @{ +*/ + +/** + Push a stack frame. + This is done automatically by container functions (which take a stack frame + pointer), but may be called by the user to push the top level container when + writing to an existing Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_push(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_Atom_Forge_Ref ref) +{ + frame->parent = forge->stack; + frame->ref = ref; + + if (ref) { + forge->stack = frame; // Don't push, so walking the stack is always safe + } + + return ref; +} + +/** Pop a stack frame. This must be called when a container is finished. */ +static inline void +lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) +{ + if (frame->ref) { + // If frame has a valid ref, it must be the top of the stack + assert(frame == forge->stack); + forge->stack = frame->parent; + } + // Otherwise, frame was not pushed because of overflow, do nothing +} + +/** Return true iff the top of the stack has the given type. */ +static inline bool +lv2_atom_forge_top_is(LV2_Atom_Forge* forge, uint32_t type) +{ + return forge->stack && forge->stack->ref && + (lv2_atom_forge_deref(forge, forge->stack->ref)->type == type); +} + +/** Return true iff `type` is an atom:Object. */ +static inline bool +lv2_atom_forge_is_object_type(const LV2_Atom_Forge* forge, uint32_t type) +{ + return (type == forge->Object || type == forge->Blank || + type == forge->Resource); +} + +/** Return true iff `type` is an atom:Object with a blank ID. */ +static inline bool +lv2_atom_forge_is_blank(const LV2_Atom_Forge* forge, + uint32_t type, + const LV2_Atom_Object_Body* body) +{ + return (type == forge->Blank || (type == forge->Object && body->id == 0)); +} + +/** + @} + @name Output Configuration + @{ +*/ + +/** Set the output buffer where `forge` will write atoms. */ +static inline void +lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size) +{ + forge->buf = buf; + forge->size = (uint32_t)size; + forge->offset = 0; + forge->deref = NULL; + forge->sink = NULL; + forge->handle = NULL; + forge->stack = NULL; +} + +/** + Set the sink function where `forge` will write output. + + The return value of forge functions is an LV2_Atom_Forge_Ref which is an + integer type safe to use as a pointer but is otherwise opaque. The sink + function must return a ref that can be dereferenced to access as least + sizeof(LV2_Atom) bytes of the written data, so sizes can be updated. For + ringbuffers, this should be possible as long as the size of the buffer is a + multiple of sizeof(LV2_Atom), since atoms are always aligned. + + Note that 0 is an invalid reference, so if you are using a buffer offset be + sure to offset it such that 0 is never a valid reference. You will get + confusing errors otherwise. +*/ +static inline void +lv2_atom_forge_set_sink(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Sink sink, + LV2_Atom_Forge_Deref_Func deref, + LV2_Atom_Forge_Sink_Handle handle) +{ + forge->buf = NULL; + forge->size = forge->offset = 0; + forge->deref = deref; + forge->sink = sink; + forge->handle = handle; + forge->stack = NULL; +} + +/** + @} + @name Low Level Output + @{ +*/ + +/** + Write raw output. This is used internally, but is also useful for writing + atom types not explicitly supported by the forge API. Note the caller is + responsible for ensuring the output is appropriately padded. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size) +{ + LV2_Atom_Forge_Ref out = 0; + if (forge->sink) { + out = forge->sink(forge->handle, data, size); + } else { + out = (LV2_Atom_Forge_Ref)forge->buf + forge->offset; + uint8_t* mem = forge->buf + forge->offset; + if (forge->offset + size > forge->size) { + return 0; + } + forge->offset += size; + memcpy(mem, data, size); + } + for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) { + lv2_atom_forge_deref(forge, f->ref)->size += size; + } + return out; +} + +/** Pad output accordingly so next write is 64-bit aligned. */ +static inline void +lv2_atom_forge_pad(LV2_Atom_Forge* forge, uint32_t written) +{ + const uint64_t pad = 0; + const uint32_t pad_size = lv2_atom_pad_size(written) - written; + lv2_atom_forge_raw(forge, &pad, pad_size); +} + +/** Write raw output, padding to 64-bits as necessary. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size) +{ + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, data, size); + if (out) { + lv2_atom_forge_pad(forge, size); + } + return out; +} + +/** Write a null-terminated string body. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_string_body(LV2_Atom_Forge* forge, const char* str, uint32_t len) +{ + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, str, len); + if (out && (out = lv2_atom_forge_raw(forge, "", 1))) { + lv2_atom_forge_pad(forge, len + 1); + } + return out; +} + +/** + @} + @name Atom Output + @{ +*/ + +/** Write an atom:Atom header. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_atom(LV2_Atom_Forge* forge, uint32_t size, uint32_t type) +{ + const LV2_Atom a = {size, type}; + return lv2_atom_forge_raw(forge, &a, sizeof(a)); +} + +/** Write a primitive (fixed-size) atom. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a) +{ + return ( + lv2_atom_forge_top_is(forge, forge->Vector) + ? lv2_atom_forge_raw(forge, LV2_ATOM_BODY_CONST(a), a->size) + : lv2_atom_forge_write(forge, a, (uint32_t)sizeof(LV2_Atom) + a->size)); +} + +/** Write an atom:Int. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_int(LV2_Atom_Forge* forge, int32_t val) +{ + const LV2_Atom_Int a = {{sizeof(val), forge->Int}, val}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom:Long. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_long(LV2_Atom_Forge* forge, int64_t val) +{ + const LV2_Atom_Long a = {{sizeof(val), forge->Long}, val}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom:Float. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_float(LV2_Atom_Forge* forge, float val) +{ + const LV2_Atom_Float a = {{sizeof(val), forge->Float}, val}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom:Double. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_double(LV2_Atom_Forge* forge, double val) +{ + const LV2_Atom_Double a = {{sizeof(val), forge->Double}, val}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom:Bool. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val) +{ + const LV2_Atom_Bool a = {{sizeof(int32_t), forge->Bool}, val ? 1 : 0}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom:URID. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_urid(LV2_Atom_Forge* forge, LV2_URID id) +{ + const LV2_Atom_URID a = {{sizeof(id), forge->URID}, id}; + return lv2_atom_forge_primitive(forge, (const LV2_Atom*)&a); +} + +/** Write an atom compatible with atom:String. Used internally. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_typed_string(LV2_Atom_Forge* forge, + uint32_t type, + const char* str, + uint32_t len) +{ + const LV2_Atom_String a = {{len + 1, type}}; + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); + if (out) { + if (!lv2_atom_forge_string_body(forge, str, len)) { + LV2_Atom* atom = lv2_atom_forge_deref(forge, out); + atom->size = atom->type = 0; + out = 0; + } + } + return out; +} + +/** Write an atom:String. Note that `str` need not be NULL terminated. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_string(LV2_Atom_Forge* forge, const char* str, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->String, str, len); +} + +/** + Write an atom:URI. Note that `uri` need not be NULL terminated. + This does not map the URI, but writes the complete URI string. To write + a mapped URI, use lv2_atom_forge_urid(). +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_uri(LV2_Atom_Forge* forge, const char* uri, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->URI, uri, len); +} + +/** Write an atom:Path. Note that `path` need not be NULL terminated. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_path(LV2_Atom_Forge* forge, const char* path, uint32_t len) +{ + return lv2_atom_forge_typed_string(forge, forge->Path, path, len); +} + +/** Write an atom:Literal. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_literal(LV2_Atom_Forge* forge, + const char* str, + uint32_t len, + uint32_t datatype, + uint32_t lang) +{ + const LV2_Atom_Literal a = { + {(uint32_t)(sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1), + forge->Literal}, + {datatype, lang}}; + LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a)); + if (out) { + if (!lv2_atom_forge_string_body(forge, str, len)) { + LV2_Atom* atom = lv2_atom_forge_deref(forge, out); + atom->size = atom->type = 0; + out = 0; + } + } + return out; +} + +/** Start an atom:Vector. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_vector_head(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t child_size, + uint32_t child_type) +{ + const LV2_Atom_Vector a = {{sizeof(LV2_Atom_Vector_Body), forge->Vector}, + {child_size, child_type}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** Write a complete atom:Vector. */ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_vector(LV2_Atom_Forge* forge, + uint32_t child_size, + uint32_t child_type, + uint32_t n_elems, + const void* elems) +{ + const LV2_Atom_Vector a = { + {(uint32_t)sizeof(LV2_Atom_Vector_Body) + n_elems * child_size, + forge->Vector}, + {child_size, child_type}}; + LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); + if (out) { + lv2_atom_forge_write(forge, elems, child_size * n_elems); + } + return out; +} + +/** + Write the header of an atom:Tuple. + + The passed frame will be initialised to represent this tuple. To complete + the tuple, write a sequence of atoms, then pop the frame with + lv2_atom_forge_pop(). + + For example: + @code + // Write tuple (1, 2.0) + LV2_Atom_Forge_Frame frame; + LV2_Atom* tup = (LV2_Atom*)lv2_atom_forge_tuple(forge, &frame); + lv2_atom_forge_int(forge, 1); + lv2_atom_forge_float(forge, 2.0); + lv2_atom_forge_pop(forge, &frame); + @endcode +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame) +{ + const LV2_Atom_Tuple a = {{0, forge->Tuple}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write the header of an atom:Object. + + The passed frame will be initialised to represent this object. To complete + the object, write a sequence of properties, then pop the frame with + lv2_atom_forge_pop(). + + For example: + @code + LV2_URID eg_Cat = map("http://example.org/Cat"); + LV2_URID eg_name = map("http://example.org/name"); + + // Start object with type eg_Cat and blank ID + LV2_Atom_Forge_Frame frame; + lv2_atom_forge_object(forge, &frame, 0, eg_Cat); + + // Append property eg:name = "Hobbes" + lv2_atom_forge_key(forge, eg_name); + lv2_atom_forge_string(forge, "Hobbes", strlen("Hobbes")); + + // Finish object + lv2_atom_forge_pop(forge, &frame); + @endcode +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_object(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_URID id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + {(uint32_t)sizeof(LV2_Atom_Object_Body), forge->Object}, {id, otype}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + The same as lv2_atom_forge_object(), but for object:Resource. + + This function is deprecated and should not be used in new code. + Use lv2_atom_forge_object() directly instead. +*/ +LV2_DEPRECATED +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_resource(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + LV2_URID id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + {(uint32_t)sizeof(LV2_Atom_Object_Body), forge->Resource}, {id, otype}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + The same as lv2_atom_forge_object(), but for object:Blank. + + This function is deprecated and should not be used in new code. + Use lv2_atom_forge_object() directly instead. +*/ +LV2_DEPRECATED +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_blank(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t id, + LV2_URID otype) +{ + const LV2_Atom_Object a = { + {(uint32_t)sizeof(LV2_Atom_Object_Body), forge->Blank}, {id, otype}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write a property key in an Object, to be followed by the value. + + See lv2_atom_forge_object() documentation for an example. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_key(LV2_Atom_Forge* forge, LV2_URID key) +{ + const LV2_Atom_Property_Body a = {key, 0, {0, 0}}; + return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); +} + +/** + Write the header for a property body in an object, with context. + + If you do not need the context, which is almost certainly the case, + use the simpler lv2_atom_forge_key() instead. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_property_head(LV2_Atom_Forge* forge, + LV2_URID key, + LV2_URID context) +{ + const LV2_Atom_Property_Body a = {key, context, {0, 0}}; + return lv2_atom_forge_write(forge, &a, 2 * (uint32_t)sizeof(uint32_t)); +} + +/** + Write the header for a Sequence. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, + LV2_Atom_Forge_Frame* frame, + uint32_t unit) +{ + const LV2_Atom_Sequence a = { + {(uint32_t)sizeof(LV2_Atom_Sequence_Body), forge->Sequence}, {unit, 0}}; + return lv2_atom_forge_push( + forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a))); +} + +/** + Write the time stamp header of an Event (in a Sequence) in audio frames. + After this, call the appropriate forge method(s) to write the body. Note + the returned reference is to an LV2_Event which is NOT an Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) +{ + return lv2_atom_forge_write(forge, &frames, sizeof(frames)); +} + +/** + Write the time stamp header of an Event (in a Sequence) in beats. After + this, call the appropriate forge method(s) to write the body. Note the + returned reference is to an LV2_Event which is NOT an Atom. +*/ +static inline LV2_Atom_Forge_Ref +lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats) +{ + return lv2_atom_forge_write(forge, &beats, sizeof(beats)); +} + +LV2_RESTORE_WARNINGS + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} + @} +*/ + +#endif /* LV2_ATOM_FORGE_H */ diff --git a/include/lv2/atom/util.h b/include/lv2/atom/util.h new file mode 100644 index 0000000..16d2c00 --- /dev/null +++ b/include/lv2/atom/util.h @@ -0,0 +1,523 @@ +/* + Copyright 2008-2015 David Robillard <d@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. +*/ + +#ifndef LV2_ATOM_UTIL_H +#define LV2_ATOM_UTIL_H + +/** + @file util.h Helper functions for the LV2 Atom extension. + + Note these functions are all static inline, do not take their address. + + This header is non-normative, it is provided for convenience. +*/ + +/** + @defgroup util Utilities + @ingroup atom + + Utilities for working with atoms. + + @{ +*/ + +#include "lv2/atom/atom.h" + +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Pad a size to 64 bits. */ +static inline uint32_t +lv2_atom_pad_size(uint32_t size) +{ + return (size + 7U) & (~7U); +} + +/** Return the total size of `atom`, including the header. */ +static inline uint32_t +lv2_atom_total_size(const LV2_Atom* atom) +{ + return (uint32_t)sizeof(LV2_Atom) + atom->size; +} + +/** Return true iff `atom` is null. */ +static inline bool +lv2_atom_is_null(const LV2_Atom* atom) +{ + return !atom || (atom->type == 0 && atom->size == 0); +} + +/** Return true iff `a` is equal to `b`. */ +static inline bool +lv2_atom_equals(const LV2_Atom* a, const LV2_Atom* b) +{ + return (a == b) || ((a->type == b->type) && (a->size == b->size) && + !memcmp(a + 1, b + 1, a->size)); +} + +/** + @name Sequence Iterator + @{ +*/ + +/** Get an iterator pointing to the first event in a Sequence body. */ +static inline LV2_Atom_Event* +lv2_atom_sequence_begin(const LV2_Atom_Sequence_Body* body) +{ + return (LV2_Atom_Event*)(body + 1); +} + +/** Get an iterator pointing to the end of a Sequence body. */ +static inline LV2_Atom_Event* +lv2_atom_sequence_end(const LV2_Atom_Sequence_Body* body, uint32_t size) +{ + return (LV2_Atom_Event*)((const uint8_t*)body + lv2_atom_pad_size(size)); +} + +/** Return true iff `i` has reached the end of `body`. */ +static inline bool +lv2_atom_sequence_is_end(const LV2_Atom_Sequence_Body* body, + uint32_t size, + const LV2_Atom_Event* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the element following `i`. */ +static inline LV2_Atom_Event* +lv2_atom_sequence_next(const LV2_Atom_Event* i) +{ + return (LV2_Atom_Event*)((const uint8_t*)i + sizeof(LV2_Atom_Event) + + lv2_atom_pad_size(i->body.size)); +} + +/** + A macro for iterating over all events in a Sequence. + @param seq The sequence to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), for + example: + + @code + LV2_ATOM_SEQUENCE_FOREACH(sequence, ev) { + // Do something with ev (an LV2_Atom_Event*) here... + } + @endcode +*/ +#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \ + for (LV2_Atom_Event * iter = lv2_atom_sequence_begin(&(seq)->body); \ + !lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \ + (iter) = lv2_atom_sequence_next(iter)) + +/** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */ +#define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \ + for (LV2_Atom_Event * iter = lv2_atom_sequence_begin(body); \ + !lv2_atom_sequence_is_end(body, size, (iter)); \ + (iter) = lv2_atom_sequence_next(iter)) + +/** + @} + @name Sequence Utilities + @{ +*/ + +/** + Clear all events from `sequence`. + + This simply resets the size field, the other fields are left untouched. +*/ +static inline void +lv2_atom_sequence_clear(LV2_Atom_Sequence* seq) +{ + seq->atom.size = sizeof(LV2_Atom_Sequence_Body); +} + +/** + Append an event at the end of `sequence`. + + @param seq Sequence to append to. + @param capacity Total capacity of the sequence atom + (as set by the host for sequence output ports). + @param event Event to write. + + @return A pointer to the newly written event in `seq`, + or NULL on failure (insufficient space). +*/ +static inline LV2_Atom_Event* +lv2_atom_sequence_append_event(LV2_Atom_Sequence* seq, + uint32_t capacity, + const LV2_Atom_Event* event) +{ + const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; + if (capacity - seq->atom.size < total_size) { + return NULL; + } + + LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size); + memcpy(e, event, total_size); + + seq->atom.size += lv2_atom_pad_size(total_size); + + return e; +} + +/** + @} + @name Tuple Iterator + @{ +*/ + +/** Get an iterator pointing to the first element in `tup`. */ +static inline LV2_Atom* +lv2_atom_tuple_begin(const LV2_Atom_Tuple* tup) +{ + return (LV2_Atom*)(LV2_ATOM_BODY(tup)); +} + +/** Return true iff `i` has reached the end of `body`. */ +static inline bool +lv2_atom_tuple_is_end(const void* body, uint32_t size, const LV2_Atom* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the element following `i`. */ +static inline LV2_Atom* +lv2_atom_tuple_next(const LV2_Atom* i) +{ + return (LV2_Atom*)((const uint8_t*)i + sizeof(LV2_Atom) + + lv2_atom_pad_size(i->size)); +} + +/** + A macro for iterating over all properties of a Tuple. + @param tuple The tuple to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), for + example: + + @code + LV2_ATOM_TUPLE_FOREACH(tuple, elem) { + // Do something with elem (an LV2_Atom*) here... + } + @endcode +*/ +#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \ + for (LV2_Atom * iter = lv2_atom_tuple_begin(tuple); \ + !lv2_atom_tuple_is_end( \ + LV2_ATOM_BODY(tuple), (tuple)->atom.size, (iter)); \ + (iter) = lv2_atom_tuple_next(iter)) + +/** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */ +#define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \ + for (LV2_Atom * iter = (LV2_Atom*)(body); \ + !lv2_atom_tuple_is_end(body, size, (iter)); \ + (iter) = lv2_atom_tuple_next(iter)) + +/** + @} + @name Object Iterator + @{ +*/ + +/** Return a pointer to the first property in `body`. */ +static inline LV2_Atom_Property_Body* +lv2_atom_object_begin(const LV2_Atom_Object_Body* body) +{ + return (LV2_Atom_Property_Body*)(body + 1); +} + +/** Return true iff `i` has reached the end of `obj`. */ +static inline bool +lv2_atom_object_is_end(const LV2_Atom_Object_Body* body, + uint32_t size, + const LV2_Atom_Property_Body* i) +{ + return (const uint8_t*)i >= ((const uint8_t*)body + size); +} + +/** Return an iterator to the property following `i`. */ +static inline LV2_Atom_Property_Body* +lv2_atom_object_next(const LV2_Atom_Property_Body* i) +{ + const LV2_Atom* const value = + (const LV2_Atom*)((const uint8_t*)i + 2 * sizeof(uint32_t)); + return (LV2_Atom_Property_Body*)((const uint8_t*)i + + lv2_atom_pad_size( + (uint32_t)sizeof(LV2_Atom_Property_Body) + + value->size)); +} + +/** + A macro for iterating over all properties of an Object. + @param obj The object to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), for + example: + + @code + LV2_ATOM_OBJECT_FOREACH(object, i) { + // Do something with i (an LV2_Atom_Property_Body*) here... + } + @endcode +*/ +#define LV2_ATOM_OBJECT_FOREACH(obj, iter) \ + for (LV2_Atom_Property_Body * iter = lv2_atom_object_begin(&(obj)->body); \ + !lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \ + (iter) = lv2_atom_object_next(iter)) + +/** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */ +#define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \ + for (LV2_Atom_Property_Body * iter = lv2_atom_object_begin(body); \ + !lv2_atom_object_is_end(body, size, (iter)); \ + (iter) = lv2_atom_object_next(iter)) + +/** + @} + @name Object Query + @{ +*/ + +/** A single entry in an Object query. */ +typedef struct { + uint32_t key; /**< Key to query (input set by user) */ + const LV2_Atom** value; /**< Found value (output set by query function) */ +} LV2_Atom_Object_Query; + +/** Sentinel for lv2_atom_object_query(). */ +static const LV2_Atom_Object_Query LV2_ATOM_OBJECT_QUERY_END = {0, NULL}; + +/** + Get an object's values for various keys. + + The value pointer of each item in `query` will be set to the location of + the corresponding value in `object`. Every value pointer in `query` MUST + be initialised to NULL. This function reads `object` in a single linear + sweep. By allocating `query` on the stack, objects can be "queried" + quickly without allocating any memory. This function is realtime safe. + + This function can only do "flat" queries, it is not smart enough to match + variables in nested objects. + + For example: + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + LV2_Atom_Object_Query q[] = { + { urids.eg_name, &name }, + { urids.eg_age, &age }, + LV2_ATOM_OBJECT_QUERY_END + }; + lv2_atom_object_query(obj, q); + // name and age are now set to the appropriate values in obj, or NULL. + @endcode +*/ +static inline int +lv2_atom_object_query(const LV2_Atom_Object* object, + LV2_Atom_Object_Query* query) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of query keys so we can short-circuit when done */ + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + ++n_queries; + } + + LV2_ATOM_OBJECT_FOREACH (object, prop) { + for (LV2_Atom_Object_Query* q = query; q->key; ++q) { + if (q->key == prop->key && !*q->value) { + *q->value = &prop->value; + if (++matches == n_queries) { + return matches; + } + break; + } + } + } + return matches; +} + +/** + Body only version of lv2_atom_object_get(). +*/ +static inline int +lv2_atom_object_body_get(uint32_t size, const LV2_Atom_Object_Body* body, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, body); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**)) { + va_end(args); + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_BODY_FOREACH (body, size, prop) { + va_start(args, body); + for (int i = 0; i < n_queries; ++i) { + uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + if (qkey == prop->key && !*qval) { + *qval = &prop->value; + if (++matches == n_queries) { + va_end(args); + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + Variable argument version of lv2_atom_object_query(). + + This is nicer-looking in code, but a bit more error-prone since it is not + type safe and the argument list must be terminated. + + The arguments should be a series of uint32_t key and const LV2_Atom** value + pairs, terminated by a zero key. The value pointers MUST be initialized to + NULL. For example: + + @code + const LV2_Atom* name = NULL; + const LV2_Atom* age = NULL; + lv2_atom_object_get(obj, + uris.name_key, &name, + uris.age_key, &age, + 0); + @endcode +*/ +static inline int +lv2_atom_object_get(const LV2_Atom_Object* object, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, object); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**)) { + va_end(args); + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_FOREACH (object, prop) { + va_start(args, object); + for (int i = 0; i < n_queries; ++i) { + uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + if (qkey == prop->key && !*qval) { + *qval = &prop->value; + if (++matches == n_queries) { + va_end(args); + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +/** + Variable argument version of lv2_atom_object_query() with types. + + This is like lv2_atom_object_get(), but each entry has an additional + parameter to specify the required type. Only atoms with a matching type + will be selected. + + The arguments should be a series of uint32_t key, const LV2_Atom**, uint32_t + type triples, terminated by a zero key. The value pointers MUST be + initialized to NULL. For example: + + @code + const LV2_Atom_String* name = NULL; + const LV2_Atom_Int* age = NULL; + lv2_atom_object_get(obj, + uris.name_key, &name, uris.atom_String, + uris.age_key, &age, uris.atom_Int + 0); + @endcode +*/ +static inline int +lv2_atom_object_get_typed(const LV2_Atom_Object* object, ...) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of keys so we can short-circuit when done */ + va_list args; + va_start(args, object); + for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { + if (!va_arg(args, const LV2_Atom**) || !va_arg(args, uint32_t)) { + va_end(args); + return -1; + } + } + va_end(args); + + LV2_ATOM_OBJECT_FOREACH (object, prop) { + va_start(args, object); + for (int i = 0; i < n_queries; ++i) { + const uint32_t qkey = va_arg(args, uint32_t); + const LV2_Atom** qval = va_arg(args, const LV2_Atom**); + const uint32_t qtype = va_arg(args, uint32_t); + if (!*qval && qkey == prop->key && qtype == prop->value.type) { + *qval = &prop->value; + if (++matches == n_queries) { + va_end(args); + return matches; + } + break; + } + } + va_end(args); + } + return matches; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} + @} +*/ + +#endif /* LV2_ATOM_UTIL_H */ diff --git a/include/lv2/buf-size/buf-size.h b/include/lv2/buf-size/buf-size.h new file mode 100644 index 0000000..d96e17d --- /dev/null +++ b/include/lv2/buf-size/buf-size.h @@ -0,0 +1,51 @@ +/* + Copyright 2007-2016 David Robillard <d@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. +*/ + +#ifndef LV2_BUF_SIZE_H +#define LV2_BUF_SIZE_H + +/** + @defgroup buf-size Buffer Size + @ingroup lv2 + + Access to, and restrictions on, buffer sizes. + + See <http://lv2plug.in/ns/ext/buf-size> for details. + + @{ +*/ + +// clang-format off + +#define LV2_BUF_SIZE_URI "http://lv2plug.in/ns/ext/buf-size" ///< http://lv2plug.in/ns/ext/buf-size +#define LV2_BUF_SIZE_PREFIX LV2_BUF_SIZE_URI "#" ///< http://lv2plug.in/ns/ext/buf-size# + +#define LV2_BUF_SIZE__boundedBlockLength LV2_BUF_SIZE_PREFIX "boundedBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#boundedBlockLength +#define LV2_BUF_SIZE__coarseBlockLength LV2_BUF_SIZE_PREFIX "coarseBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#coarseBlockLength +#define LV2_BUF_SIZE__fixedBlockLength LV2_BUF_SIZE_PREFIX "fixedBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#fixedBlockLength +#define LV2_BUF_SIZE__maxBlockLength LV2_BUF_SIZE_PREFIX "maxBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#maxBlockLength +#define LV2_BUF_SIZE__minBlockLength LV2_BUF_SIZE_PREFIX "minBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#minBlockLength +#define LV2_BUF_SIZE__nominalBlockLength LV2_BUF_SIZE_PREFIX "nominalBlockLength" ///< http://lv2plug.in/ns/ext/buf-size#nominalBlockLength +#define LV2_BUF_SIZE__powerOf2BlockLength LV2_BUF_SIZE_PREFIX "powerOf2BlockLength" ///< http://lv2plug.in/ns/ext/buf-size#powerOf2BlockLength +#define LV2_BUF_SIZE__sequenceSize LV2_BUF_SIZE_PREFIX "sequenceSize" ///< http://lv2plug.in/ns/ext/buf-size#sequenceSize + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_BUF_SIZE_H */ diff --git a/include/lv2/core/attributes.h b/include/lv2/core/attributes.h new file mode 100644 index 0000000..81791a2 --- /dev/null +++ b/include/lv2/core/attributes.h @@ -0,0 +1,59 @@ +/* + Copyright 2018 David Robillard <d@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. +*/ + +#ifndef LV2_CORE_ATTRIBUTES_H +#define LV2_CORE_ATTRIBUTES_H + +/** + @defgroup attributes Attributes + @ingroup lv2 + + Macros for source code attributes. + + @{ +*/ + +#if defined(__GNUC__) && __GNUC__ > 3 +# define LV2_DEPRECATED __attribute__((__deprecated__)) +#else +# define LV2_DEPRECATED +#endif + +#if defined(__clang__) +# define LV2_DISABLE_DEPRECATION_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif defined(__GNUC__) && __GNUC__ > 4 +# define LV2_DISABLE_DEPRECATION_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#else +# define LV2_DISABLE_DEPRECATION_WARNINGS +#endif + +#if defined(__clang__) +# define LV2_RESTORE_WARNINGS _Pragma("clang diagnostic pop") +#elif defined(__GNUC__) && __GNUC__ > 4 +# define LV2_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") +#else +# define LV2_RESTORE_WARNINGS +#endif + +/** + @} +*/ + +#endif /* LV2_CORE_ATTRIBUTES_H */ diff --git a/include/lv2/core/lv2.h b/include/lv2/core/lv2.h new file mode 100644 index 0000000..84c40a5 --- /dev/null +++ b/include/lv2/core/lv2.h @@ -0,0 +1,485 @@ +/* + LV2 - An audio plugin interface specification. + Copyright 2006-2012 Steve Harris, David Robillard. + + Based on LADSPA, Copyright 2000-2002 Richard W.E. Furse, + Paul Barton-Davis, Stefan Westerfeld. + + 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. +*/ + +#ifndef LV2_H_INCLUDED +#define LV2_H_INCLUDED + +/** + @defgroup lv2 LV2 + + The LV2 specification. + + @{ +*/ + +/** + @defgroup lv2core LV2 Core + + Core LV2 specification. + + See <http://lv2plug.in/ns/lv2core> for details. + + @{ +*/ + +#include <stdint.h> + +// clang-format off + +#define LV2_CORE_URI "http://lv2plug.in/ns/lv2core" ///< http://lv2plug.in/ns/lv2core +#define LV2_CORE_PREFIX LV2_CORE_URI "#" ///< http://lv2plug.in/ns/lv2core# + +#define LV2_CORE__AllpassPlugin LV2_CORE_PREFIX "AllpassPlugin" ///< http://lv2plug.in/ns/lv2core#AllpassPlugin +#define LV2_CORE__AmplifierPlugin LV2_CORE_PREFIX "AmplifierPlugin" ///< http://lv2plug.in/ns/lv2core#AmplifierPlugin +#define LV2_CORE__AnalyserPlugin LV2_CORE_PREFIX "AnalyserPlugin" ///< http://lv2plug.in/ns/lv2core#AnalyserPlugin +#define LV2_CORE__AudioPort LV2_CORE_PREFIX "AudioPort" ///< http://lv2plug.in/ns/lv2core#AudioPort +#define LV2_CORE__BandpassPlugin LV2_CORE_PREFIX "BandpassPlugin" ///< http://lv2plug.in/ns/lv2core#BandpassPlugin +#define LV2_CORE__CVPort LV2_CORE_PREFIX "CVPort" ///< http://lv2plug.in/ns/lv2core#CVPort +#define LV2_CORE__ChorusPlugin LV2_CORE_PREFIX "ChorusPlugin" ///< http://lv2plug.in/ns/lv2core#ChorusPlugin +#define LV2_CORE__CombPlugin LV2_CORE_PREFIX "CombPlugin" ///< http://lv2plug.in/ns/lv2core#CombPlugin +#define LV2_CORE__CompressorPlugin LV2_CORE_PREFIX "CompressorPlugin" ///< http://lv2plug.in/ns/lv2core#CompressorPlugin +#define LV2_CORE__ConstantPlugin LV2_CORE_PREFIX "ConstantPlugin" ///< http://lv2plug.in/ns/lv2core#ConstantPlugin +#define LV2_CORE__ControlPort LV2_CORE_PREFIX "ControlPort" ///< http://lv2plug.in/ns/lv2core#ControlPort +#define LV2_CORE__ConverterPlugin LV2_CORE_PREFIX "ConverterPlugin" ///< http://lv2plug.in/ns/lv2core#ConverterPlugin +#define LV2_CORE__DelayPlugin LV2_CORE_PREFIX "DelayPlugin" ///< http://lv2plug.in/ns/lv2core#DelayPlugin +#define LV2_CORE__DistortionPlugin LV2_CORE_PREFIX "DistortionPlugin" ///< http://lv2plug.in/ns/lv2core#DistortionPlugin +#define LV2_CORE__DynamicsPlugin LV2_CORE_PREFIX "DynamicsPlugin" ///< http://lv2plug.in/ns/lv2core#DynamicsPlugin +#define LV2_CORE__EQPlugin LV2_CORE_PREFIX "EQPlugin" ///< http://lv2plug.in/ns/lv2core#EQPlugin +#define LV2_CORE__EnvelopePlugin LV2_CORE_PREFIX "EnvelopePlugin" ///< http://lv2plug.in/ns/lv2core#EnvelopePlugin +#define LV2_CORE__ExpanderPlugin LV2_CORE_PREFIX "ExpanderPlugin" ///< http://lv2plug.in/ns/lv2core#ExpanderPlugin +#define LV2_CORE__ExtensionData LV2_CORE_PREFIX "ExtensionData" ///< http://lv2plug.in/ns/lv2core#ExtensionData +#define LV2_CORE__Feature LV2_CORE_PREFIX "Feature" ///< http://lv2plug.in/ns/lv2core#Feature +#define LV2_CORE__FilterPlugin LV2_CORE_PREFIX "FilterPlugin" ///< http://lv2plug.in/ns/lv2core#FilterPlugin +#define LV2_CORE__FlangerPlugin LV2_CORE_PREFIX "FlangerPlugin" ///< http://lv2plug.in/ns/lv2core#FlangerPlugin +#define LV2_CORE__FunctionPlugin LV2_CORE_PREFIX "FunctionPlugin" ///< http://lv2plug.in/ns/lv2core#FunctionPlugin +#define LV2_CORE__GatePlugin LV2_CORE_PREFIX "GatePlugin" ///< http://lv2plug.in/ns/lv2core#GatePlugin +#define LV2_CORE__GeneratorPlugin LV2_CORE_PREFIX "GeneratorPlugin" ///< http://lv2plug.in/ns/lv2core#GeneratorPlugin +#define LV2_CORE__HighpassPlugin LV2_CORE_PREFIX "HighpassPlugin" ///< http://lv2plug.in/ns/lv2core#HighpassPlugin +#define LV2_CORE__InputPort LV2_CORE_PREFIX "InputPort" ///< http://lv2plug.in/ns/lv2core#InputPort +#define LV2_CORE__InstrumentPlugin LV2_CORE_PREFIX "InstrumentPlugin" ///< http://lv2plug.in/ns/lv2core#InstrumentPlugin +#define LV2_CORE__LimiterPlugin LV2_CORE_PREFIX "LimiterPlugin" ///< http://lv2plug.in/ns/lv2core#LimiterPlugin +#define LV2_CORE__LowpassPlugin LV2_CORE_PREFIX "LowpassPlugin" ///< http://lv2plug.in/ns/lv2core#LowpassPlugin +#define LV2_CORE__MixerPlugin LV2_CORE_PREFIX "MixerPlugin" ///< http://lv2plug.in/ns/lv2core#MixerPlugin +#define LV2_CORE__ModulatorPlugin LV2_CORE_PREFIX "ModulatorPlugin" ///< http://lv2plug.in/ns/lv2core#ModulatorPlugin +#define LV2_CORE__MultiEQPlugin LV2_CORE_PREFIX "MultiEQPlugin" ///< http://lv2plug.in/ns/lv2core#MultiEQPlugin +#define LV2_CORE__OscillatorPlugin LV2_CORE_PREFIX "OscillatorPlugin" ///< http://lv2plug.in/ns/lv2core#OscillatorPlugin +#define LV2_CORE__OutputPort LV2_CORE_PREFIX "OutputPort" ///< http://lv2plug.in/ns/lv2core#OutputPort +#define LV2_CORE__ParaEQPlugin LV2_CORE_PREFIX "ParaEQPlugin" ///< http://lv2plug.in/ns/lv2core#ParaEQPlugin +#define LV2_CORE__PhaserPlugin LV2_CORE_PREFIX "PhaserPlugin" ///< http://lv2plug.in/ns/lv2core#PhaserPlugin +#define LV2_CORE__PitchPlugin LV2_CORE_PREFIX "PitchPlugin" ///< http://lv2plug.in/ns/lv2core#PitchPlugin +#define LV2_CORE__Plugin LV2_CORE_PREFIX "Plugin" ///< http://lv2plug.in/ns/lv2core#Plugin +#define LV2_CORE__PluginBase LV2_CORE_PREFIX "PluginBase" ///< http://lv2plug.in/ns/lv2core#PluginBase +#define LV2_CORE__Point LV2_CORE_PREFIX "Point" ///< http://lv2plug.in/ns/lv2core#Point +#define LV2_CORE__Port LV2_CORE_PREFIX "Port" ///< http://lv2plug.in/ns/lv2core#Port +#define LV2_CORE__PortProperty LV2_CORE_PREFIX "PortProperty" ///< http://lv2plug.in/ns/lv2core#PortProperty +#define LV2_CORE__Resource LV2_CORE_PREFIX "Resource" ///< http://lv2plug.in/ns/lv2core#Resource +#define LV2_CORE__ReverbPlugin LV2_CORE_PREFIX "ReverbPlugin" ///< http://lv2plug.in/ns/lv2core#ReverbPlugin +#define LV2_CORE__ScalePoint LV2_CORE_PREFIX "ScalePoint" ///< http://lv2plug.in/ns/lv2core#ScalePoint +#define LV2_CORE__SimulatorPlugin LV2_CORE_PREFIX "SimulatorPlugin" ///< http://lv2plug.in/ns/lv2core#SimulatorPlugin +#define LV2_CORE__SpatialPlugin LV2_CORE_PREFIX "SpatialPlugin" ///< http://lv2plug.in/ns/lv2core#SpatialPlugin +#define LV2_CORE__Specification LV2_CORE_PREFIX "Specification" ///< http://lv2plug.in/ns/lv2core#Specification +#define LV2_CORE__SpectralPlugin LV2_CORE_PREFIX "SpectralPlugin" ///< http://lv2plug.in/ns/lv2core#SpectralPlugin +#define LV2_CORE__UtilityPlugin LV2_CORE_PREFIX "UtilityPlugin" ///< http://lv2plug.in/ns/lv2core#UtilityPlugin +#define LV2_CORE__WaveshaperPlugin LV2_CORE_PREFIX "WaveshaperPlugin" ///< http://lv2plug.in/ns/lv2core#WaveshaperPlugin +#define LV2_CORE__appliesTo LV2_CORE_PREFIX "appliesTo" ///< http://lv2plug.in/ns/lv2core#appliesTo +#define LV2_CORE__binary LV2_CORE_PREFIX "binary" ///< http://lv2plug.in/ns/lv2core#binary +#define LV2_CORE__connectionOptional LV2_CORE_PREFIX "connectionOptional" ///< http://lv2plug.in/ns/lv2core#connectionOptional +#define LV2_CORE__control LV2_CORE_PREFIX "control" ///< http://lv2plug.in/ns/lv2core#control +#define LV2_CORE__default LV2_CORE_PREFIX "default" ///< http://lv2plug.in/ns/lv2core#default +#define LV2_CORE__designation LV2_CORE_PREFIX "designation" ///< http://lv2plug.in/ns/lv2core#designation +#define LV2_CORE__documentation LV2_CORE_PREFIX "documentation" ///< http://lv2plug.in/ns/lv2core#documentation +#define LV2_CORE__enabled LV2_CORE_PREFIX "enabled" ///< http://lv2plug.in/ns/lv2core#enabled +#define LV2_CORE__enumeration LV2_CORE_PREFIX "enumeration" ///< http://lv2plug.in/ns/lv2core#enumeration +#define LV2_CORE__extensionData LV2_CORE_PREFIX "extensionData" ///< http://lv2plug.in/ns/lv2core#extensionData +#define LV2_CORE__freeWheeling LV2_CORE_PREFIX "freeWheeling" ///< http://lv2plug.in/ns/lv2core#freeWheeling +#define LV2_CORE__hardRTCapable LV2_CORE_PREFIX "hardRTCapable" ///< http://lv2plug.in/ns/lv2core#hardRTCapable +#define LV2_CORE__inPlaceBroken LV2_CORE_PREFIX "inPlaceBroken" ///< http://lv2plug.in/ns/lv2core#inPlaceBroken +#define LV2_CORE__index LV2_CORE_PREFIX "index" ///< http://lv2plug.in/ns/lv2core#index +#define LV2_CORE__integer LV2_CORE_PREFIX "integer" ///< http://lv2plug.in/ns/lv2core#integer +#define LV2_CORE__isLive LV2_CORE_PREFIX "isLive" ///< http://lv2plug.in/ns/lv2core#isLive +#define LV2_CORE__latency LV2_CORE_PREFIX "latency" ///< http://lv2plug.in/ns/lv2core#latency +#define LV2_CORE__maximum LV2_CORE_PREFIX "maximum" ///< http://lv2plug.in/ns/lv2core#maximum +#define LV2_CORE__microVersion LV2_CORE_PREFIX "microVersion" ///< http://lv2plug.in/ns/lv2core#microVersion +#define LV2_CORE__minimum LV2_CORE_PREFIX "minimum" ///< http://lv2plug.in/ns/lv2core#minimum +#define LV2_CORE__minorVersion LV2_CORE_PREFIX "minorVersion" ///< http://lv2plug.in/ns/lv2core#minorVersion +#define LV2_CORE__name LV2_CORE_PREFIX "name" ///< http://lv2plug.in/ns/lv2core#name +#define LV2_CORE__optionalFeature LV2_CORE_PREFIX "optionalFeature" ///< http://lv2plug.in/ns/lv2core#optionalFeature +#define LV2_CORE__port LV2_CORE_PREFIX "port" ///< http://lv2plug.in/ns/lv2core#port +#define LV2_CORE__portProperty LV2_CORE_PREFIX "portProperty" ///< http://lv2plug.in/ns/lv2core#portProperty +#define LV2_CORE__project LV2_CORE_PREFIX "project" ///< http://lv2plug.in/ns/lv2core#project +#define LV2_CORE__prototype LV2_CORE_PREFIX "prototype" ///< http://lv2plug.in/ns/lv2core#prototype +#define LV2_CORE__reportsLatency LV2_CORE_PREFIX "reportsLatency" ///< http://lv2plug.in/ns/lv2core#reportsLatency +#define LV2_CORE__requiredFeature LV2_CORE_PREFIX "requiredFeature" ///< http://lv2plug.in/ns/lv2core#requiredFeature +#define LV2_CORE__sampleRate LV2_CORE_PREFIX "sampleRate" ///< http://lv2plug.in/ns/lv2core#sampleRate +#define LV2_CORE__scalePoint LV2_CORE_PREFIX "scalePoint" ///< http://lv2plug.in/ns/lv2core#scalePoint +#define LV2_CORE__symbol LV2_CORE_PREFIX "symbol" ///< http://lv2plug.in/ns/lv2core#symbol +#define LV2_CORE__toggled LV2_CORE_PREFIX "toggled" ///< http://lv2plug.in/ns/lv2core#toggled + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Plugin Instance Handle. + + This is a handle for one particular instance of a plugin. It is valid to + compare to NULL (or 0 for C++) but otherwise the host MUST NOT attempt to + interpret it. +*/ +typedef void* LV2_Handle; + +/** + Feature. + + Features allow hosts to make additional functionality available to plugins + without requiring modification to the LV2 API. Extensions may define new + features and specify the `URI` and `data` to be used if necessary. + Some features, such as lv2:isLive, do not require the host to pass data. +*/ +typedef struct { + /** + A globally unique, case-sensitive identifier (URI) for this feature. + + This MUST be a valid URI string as defined by RFC 3986. + */ + const char* URI; + + /** + Pointer to arbitrary data. + + The format of this data is defined by the extension which describes the + feature with the given `URI`. + */ + void* data; +} LV2_Feature; + +/** + Plugin Descriptor. + + This structure provides the core functions necessary to instantiate and use + a plugin. +*/ +typedef struct LV2_Descriptor { + /** + A globally unique, case-sensitive identifier for this plugin. + + This MUST be a valid URI string as defined by RFC 3986. All plugins with + the same URI MUST be compatible to some degree, see + http://lv2plug.in/ns/lv2core for details. + */ + const char* URI; + + /** + Instantiate the plugin. + + Note that instance initialisation should generally occur in activate() + rather than here. If a host calls instantiate(), it MUST call cleanup() + at some point in the future. + + @param descriptor Descriptor of the plugin to instantiate. + + @param sample_rate Sample rate, in Hz, for the new plugin instance. + + @param bundle_path Path to the LV2 bundle which contains this plugin + binary. It MUST include the trailing directory separator so that simply + appending a filename will yield the path to that file in the bundle. + + @param features A NULL terminated array of LV2_Feature structs which + represent the features the host supports. Plugins may refuse to + instantiate if required features are not found here. However, hosts MUST + NOT use this as a discovery mechanism: instead, use the RDF data to + determine which features are required and do not attempt to instantiate + unsupported plugins at all. This parameter MUST NOT be NULL, i.e. a host + that supports no features MUST pass a single element array containing + NULL. + + @return A handle for the new plugin instance, or NULL if instantiation + has failed. + */ + LV2_Handle (*instantiate)(const struct LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features); + + /** + Connect a port on a plugin instance to a memory location. + + Plugin writers should be aware that the host may elect to use the same + buffer for more than one port and even use the same buffer for both + input and output (see lv2:inPlaceBroken in lv2.ttl). + + If the plugin has the feature lv2:hardRTCapable then there are various + things that the plugin MUST NOT do within the connect_port() function; + see lv2core.ttl for details. + + connect_port() MUST be called at least once for each port before run() + is called, unless that port is lv2:connectionOptional. The plugin must + pay careful attention to the block size passed to run() since the block + allocated may only just be large enough to contain the data, and is not + guaranteed to remain constant between run() calls. + + connect_port() may be called more than once for a plugin instance to + allow the host to change the buffers that the plugin is reading or + writing. These calls may be made before or after activate() or + deactivate() calls. + + @param instance Plugin instance containing the port. + + @param port Index of the port to connect. The host MUST NOT try to + connect a port index that is not defined in the plugin's RDF data. If + it does, the plugin's behaviour is undefined (a crash is likely). + + @param data_location Pointer to data of the type defined by the port + type in the plugin's RDF data (for example, an array of float for an + lv2:AudioPort). This pointer must be stored by the plugin instance and + used to read/write data when run() is called. Data present at the time + of the connect_port() call MUST NOT be considered meaningful. + */ + void (*connect_port)(LV2_Handle instance, uint32_t port, void* data_location); + + /** + Initialise a plugin instance and activate it for use. + + This is separated from instantiate() to aid real-time support and so + that hosts can reinitialise a plugin instance by calling deactivate() + and then activate(). In this case the plugin instance MUST reset all + state information dependent on the history of the plugin instance except + for any data locations provided by connect_port(). If there is nothing + for activate() to do then this field may be NULL. + + When present, hosts MUST call this function once before run() is called + for the first time. This call SHOULD be made as close to the run() call + as possible and indicates to real-time plugins that they are now live, + however plugins MUST NOT rely on a prompt call to run() after + activate(). + + The host MUST NOT call activate() again until deactivate() has been + called first. If a host calls activate(), it MUST call deactivate() at + some point in the future. Note that connect_port() may be called before + or after activate(). + */ + void (*activate)(LV2_Handle instance); + + /** + Run a plugin instance for a block. + + Note that if an activate() function exists then it must be called before + run(). If deactivate() is called for a plugin instance then run() may + not be called until activate() has been called again. + + If the plugin has the feature lv2:hardRTCapable then there are various + things that the plugin MUST NOT do within the run() function (see + lv2core.ttl for details). + + As a special case, when `sample_count` is 0, the plugin should update + any output ports that represent a single instant in time (for example, + control ports, but not audio ports). This is particularly useful for + latent plugins, which should update their latency output port so hosts + can pre-roll plugins to compute latency. Plugins MUST NOT crash when + `sample_count` is 0. + + @param instance Instance to be run. + + @param sample_count The block size (in samples) for which the plugin + instance must run. + */ + void (*run)(LV2_Handle instance, uint32_t sample_count); + + /** + Deactivate a plugin instance (counterpart to activate()). + + Hosts MUST deactivate all activated instances after they have been run() + for the last time. This call SHOULD be made as close to the last run() + call as possible and indicates to real-time plugins that they are no + longer live, however plugins MUST NOT rely on prompt deactivation. If + there is nothing for deactivate() to do then this field may be NULL + + Deactivation is not similar to pausing since the plugin instance will be + reinitialised by activate(). However, deactivate() itself MUST NOT fully + reset plugin state. For example, the host may deactivate a plugin, then + store its state (using some extension to do so). + + Hosts MUST NOT call deactivate() unless activate() was previously + called. Note that connect_port() may be called before or after + deactivate(). + */ + void (*deactivate)(LV2_Handle instance); + + /** + Clean up a plugin instance (counterpart to instantiate()). + + Once an instance of a plugin has been finished with it must be deleted + using this function. The instance handle passed ceases to be valid after + this call. + + If activate() was called for a plugin instance then a corresponding call + to deactivate() MUST be made before cleanup() is called. Hosts MUST NOT + call cleanup() unless instantiate() was previously called. + */ + void (*cleanup)(LV2_Handle instance); + + /** + Return additional plugin data defined by some extension. + + A typical use of this facility is to return a struct containing function + pointers to extend the LV2_Descriptor API. + + The actual type and meaning of the returned object MUST be specified + precisely by the extension. This function MUST return NULL for any + unsupported URI. If a plugin does not support any extension data, this + field may be NULL. + + The host is never responsible for freeing the returned value. + */ + const void* (*extension_data)(const char* uri); +} LV2_Descriptor; + +/** + Helper macro needed for LV2_SYMBOL_EXPORT when using C++. +*/ +#ifdef __cplusplus +# define LV2_SYMBOL_EXTERN extern "C" +#else +# define LV2_SYMBOL_EXTERN +#endif + +/** + Put this (LV2_SYMBOL_EXPORT) before any functions that are to be loaded + by the host as a symbol from the dynamic library. +*/ +#ifdef _WIN32 +# define LV2_SYMBOL_EXPORT LV2_SYMBOL_EXTERN __declspec(dllexport) +#else +# define LV2_SYMBOL_EXPORT \ + LV2_SYMBOL_EXTERN __attribute__((visibility("default"))) +#endif + +/** + Prototype for plugin accessor function. + + Plugins are discovered by hosts using RDF data (not by loading libraries). + See http://lv2plug.in for details on the discovery process, though most + hosts should use an existing library to implement this functionality. + + This is the simple plugin discovery API, suitable for most statically + defined plugins. Advanced plugins that need access to their bundle during + discovery can use lv2_lib_descriptor() instead. Plugin libraries MUST + include a function called "lv2_descriptor" or "lv2_lib_descriptor" with + C-style linkage, but SHOULD provide "lv2_descriptor" wherever possible. + + When it is time to load a plugin (designated by its URI), the host loads the + plugin's library, gets the lv2_descriptor() function from it, and uses this + function to find the LV2_Descriptor for the desired plugin. Plugins are + accessed by index using values from 0 upwards. This function MUST return + NULL for out of range indices, so the host can enumerate plugins by + increasing `index` until NULL is returned. + + Note that `index` has no meaning, hosts MUST NOT depend on it remaining + consistent between loads of the plugin library. +*/ +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index); + +/** + Type of the lv2_descriptor() function in a library (old discovery API). +*/ +typedef const LV2_Descriptor* (*LV2_Descriptor_Function)(uint32_t index); + +/** + Handle for a library descriptor. +*/ +typedef void* LV2_Lib_Handle; + +/** + Descriptor for a plugin library. + + To access a plugin library, the host creates an LV2_Lib_Descriptor via the + lv2_lib_descriptor() function in the shared object. +*/ +typedef struct { + /** + Opaque library data which must be passed as the first parameter to all + the methods of this struct. + */ + LV2_Lib_Handle handle; + + /** + The total size of this struct. This allows for this struct to be + expanded in the future if necessary. This MUST be set by the library to + sizeof(LV2_Lib_Descriptor). The host MUST NOT access any fields of this + struct beyond get_plugin() unless this field indicates they are present. + */ + uint32_t size; + + /** + Destroy this library descriptor and free all related resources. + */ + void (*cleanup)(LV2_Lib_Handle handle); + + /** + Plugin accessor. + + Plugins are accessed by index using values from 0 upwards. Out of range + indices MUST result in this function returning NULL, so the host can + enumerate plugins by increasing `index` until NULL is returned. + */ + const LV2_Descriptor* (*get_plugin)(LV2_Lib_Handle handle, uint32_t index); +} LV2_Lib_Descriptor; + +/** + Prototype for library accessor function. + + This is the more advanced discovery API, which allows plugin libraries to + access their bundles during discovery, which makes it possible for plugins to + be dynamically defined by files in their bundle. This API also has an + explicit cleanup function, removing any need for non-portable shared library + destructors. Simple plugins that do not require these features may use + lv2_descriptor() instead. + + This is the entry point for a plugin library. Hosts load this symbol from + the library and call this function to obtain a library descriptor which can + be used to access all the contained plugins. The returned object must not + be destroyed (using LV2_Lib_Descriptor::cleanup()) until all plugins loaded + from that library have been destroyed. +*/ +LV2_SYMBOL_EXPORT +const LV2_Lib_Descriptor* +lv2_lib_descriptor(const char* bundle_path, const LV2_Feature* const* features); + +/** + Type of the lv2_lib_descriptor() function in an LV2 library. +*/ +typedef const LV2_Lib_Descriptor* (*LV2_Lib_Descriptor_Function)( + const char* bundle_path, + const LV2_Feature* const* features); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} + @} +*/ + +#endif /* LV2_H_INCLUDED */ diff --git a/include/lv2/core/lv2_util.h b/include/lv2/core/lv2_util.h new file mode 100644 index 0000000..f3766aa --- /dev/null +++ b/include/lv2/core/lv2_util.h @@ -0,0 +1,103 @@ +/* + Copyright 2016 David Robillard <d@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 "lv2/core/lv2.h" + +#include <stdarg.h> +#include <stdbool.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#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) +{ + if (features) { + 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 = (bool)va_arg(args, int); + + *data = lv2_features_data(features, uri); + if (required && !*data) { + va_end(args); + return uri; + } + } + + va_end(args); + return NULL; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ diff --git a/include/lv2/data-access/data-access.h b/include/lv2/data-access/data-access.h new file mode 100644 index 0000000..de3b6b6 --- /dev/null +++ b/include/lv2/data-access/data-access.h @@ -0,0 +1,73 @@ +/* + Copyright 2008-2016 David Robillard <d@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. +*/ + +#ifndef LV2_DATA_ACCESS_H +#define LV2_DATA_ACCESS_H + +/** + @defgroup data-access Data Access + @ingroup lv2 + + Access to plugin extension_data() for UIs. + + See <http://lv2plug.in/ns/ext/data-access> for details. + + @{ +*/ + +// clang-format off + +#define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access" ///< http://lv2plug.in/ns/ext/data-access +#define LV2_DATA_ACCESS_PREFIX LV2_DATA_ACCESS_URI "#" ///< http://lv2plug.in/ns/ext/data-access# + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +/** + The data field of the LV2_Feature for this extension. + + To support this feature the host must pass an LV2_Feature struct to the + instantiate method with URI "http://lv2plug.in/ns/ext/data-access" + and data pointed to an instance of this struct. +*/ +typedef struct { + /** + A pointer to a method the UI can call to get data (of a type specified + by some other extension) from the plugin. + + This call never is never guaranteed to return anything, UIs should + degrade gracefully if direct access to the plugin data is not possible + (in which case this function will return NULL). + + This is for access to large data that can only possibly work if the UI + and plugin are running in the same process. For all other things, use + the normal LV2 UI communication system. + */ + const void* (*data_access)(const char* uri); +} LV2_Extension_Data_Feature; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_DATA_ACCESS_H */ diff --git a/include/lv2/dynmanifest/dynmanifest.h b/include/lv2/dynmanifest/dynmanifest.h new file mode 100644 index 0000000..674577b --- /dev/null +++ b/include/lv2/dynmanifest/dynmanifest.h @@ -0,0 +1,160 @@ +/* + Dynamic manifest specification for LV2 + Copyright 2008-2011 Stefano D'Angelo <zanga.mail@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. +*/ + +#ifndef LV2_DYN_MANIFEST_H_INCLUDED +#define LV2_DYN_MANIFEST_H_INCLUDED + +/** + @defgroup dynmanifest Dynamic Manifest + @ingroup lv2 + + Support for dynamic data generation. + + See <http://lv2plug.in/ns/ext/dynmanifest> for details. + + @{ +*/ + +#include "lv2/core/lv2.h" + +#include <stdio.h> + +// clang-format off + +#define LV2_DYN_MANIFEST_URI "http://lv2plug.in/ns/ext/dynmanifest" ///< http://lv2plug.in/ns/ext/dynmanifest +#define LV2_DYN_MANIFEST_PREFIX LV2_DYN_MANIFEST_URI "#" ///< http://lv2plug.in/ns/ext/dynmanifest# + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Dynamic manifest generator handle. + + This handle indicates a particular status of a dynamic manifest generator. + The host MUST NOT attempt to interpret it and, unlikely LV2_Handle, it is + NOT even valid to compare this to NULL. The dynamic manifest generator MAY + use it to reference internal data. +*/ +typedef void* LV2_Dyn_Manifest_Handle; + +/** + Generate the dynamic manifest. + + @param handle Pointer to an uninitialized dynamic manifest generator handle. + + @param features NULL terminated array of LV2_Feature structs which represent + the features the host supports. The dynamic manifest generator may refuse to + (re)generate the dynamic manifest if required features are not found here + (however hosts SHOULD NOT use this as a discovery mechanism, instead of + reading the static manifest file). This array must always exist; if a host + has no features, it MUST pass a single element array containing NULL. + + @return 0 on success, otherwise a non-zero error code. The host SHOULD + evaluate the result of the operation by examining the returned value and + MUST NOT try to interpret the value of handle. +*/ +int +lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle* handle, + const LV2_Feature* const* features); + +/** + Fetch a "list" of subject URIs described in the dynamic manifest. + + The dynamic manifest generator has to fill the resource only with the needed + triples to make the host aware of the "objects" it wants to expose. For + example, if the plugin library exposes a regular LV2 plugin, it should + output only a triple like the following: + + <http://example.org/plugin> a lv2:Plugin . + + The objects that are eligible for exposure are those that would need to be + represented by a subject node in a static manifest. + + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable, empty resource to + this function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the end of the stream (for example, using only + fprintf(), fwrite() and similar). + + @return 0 on success, otherwise a non-zero error code. +*/ +int +lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle, FILE* fp); + +/** + Function that fetches data related to a specific URI. + + The dynamic manifest generator has to fill the resource with data related to + object represented by the given URI. For example, if the library exposes a + regular LV2 plugin whose URI, as retrieved by the host using + lv2_dyn_manifest_get_subjects() is http://example.org/plugin then it + should output something like: + + <pre> + <http://example.org/plugin> + a lv2:Plugin ; + doap:name "My Plugin" ; + lv2:binary <mylib.so> ; + etc:etc "..." . + </pre> + + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable resource to this + function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the current position of the stream (for example, using + only fprintf(), fwrite() and similar). + + @param uri URI to get data about (in the "plain" form, i.e., absolute URI + without Turtle prefixes). + + @return 0 on success, otherwise a non-zero error code. +*/ +int +lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle, + FILE* fp, + const char* uri); + +/** + Function that ends the operations on the dynamic manifest generator. + + This function SHOULD be used by the dynamic manifest generator to perform + cleanup operations, etc. + + Once this function is called, referring to handle will cause undefined + behavior. + + @param handle Dynamic manifest generator handle. +*/ +void +lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_DYN_MANIFEST_H_INCLUDED */ diff --git a/include/lv2/event/event-helpers.h b/include/lv2/event/event-helpers.h new file mode 100644 index 0000000..bf1b885 --- /dev/null +++ b/include/lv2/event/event-helpers.h @@ -0,0 +1,255 @@ +/* + Copyright 2008-2015 David Robillard <d@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. +*/ + +#ifndef LV2_EVENT_HELPERS_H +#define LV2_EVENT_HELPERS_H + +/** + @file event-helpers.h Helper functions for the LV2 Event extension + <http://lv2plug.in/ns/ext/event>. +*/ + +#include "lv2/core/attributes.h" +#include "lv2/event/event.h" + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +LV2_DISABLE_DEPRECATION_WARNINGS + +/** @file + * Helper functions for the LV2 Event extension + * <http://lv2plug.in/ns/ext/event>. + * + * These functions are provided for convenience only, use of them is not + * required for supporting lv2ev (i.e. the events extension is defined by the + * raw buffer format described in lv2_event.h and NOT by this API). + * + * Note that these functions are all static inline which basically means: + * do not take the address of these functions. */ + +/** Pad a size to 64 bits (for event sizes) */ +static inline uint16_t +lv2_event_pad_size(uint16_t size) +{ + return (uint16_t)((size + 7U) & ~7U); +} + +/** Initialize (empty, reset..) an existing event buffer. + * The contents of buf are ignored entirely and overwritten, except capacity + * which is unmodified. */ +static inline void +lv2_event_buffer_reset(LV2_Event_Buffer* buf, + uint16_t stamp_type, + uint8_t* data) +{ + buf->data = data; + buf->header_size = sizeof(LV2_Event_Buffer); + buf->stamp_type = stamp_type; + buf->event_count = 0; + buf->size = 0; +} + +/** Allocate a new, empty event buffer. */ +static inline LV2_Event_Buffer* +lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type) +{ + const size_t size = sizeof(LV2_Event_Buffer) + capacity; + LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size); + if (buf != NULL) { + buf->capacity = capacity; + lv2_event_buffer_reset(buf, stamp_type, (uint8_t*)(buf + 1)); + return buf; + } + return NULL; +} + +/** An iterator over an LV2_Event_Buffer. + * + * Multiple simultaneous read iterators over a single buffer is fine, + * but changing the buffer invalidates all iterators. */ +typedef struct { + LV2_Event_Buffer* buf; + uint32_t offset; +} LV2_Event_Iterator; + +/** Reset an iterator to point to the start of `buf`. + * @return True if `iter` is valid, otherwise false (buffer is empty) */ +static inline bool +lv2_event_begin(LV2_Event_Iterator* iter, LV2_Event_Buffer* buf) +{ + iter->buf = buf; + iter->offset = 0; + return (buf->size > 0); +} + +/** Check if `iter` is valid. + * @return True if `iter` is valid, otherwise false (past end of buffer) */ +static inline bool +lv2_event_is_valid(LV2_Event_Iterator* iter) +{ + return (iter->buf && (iter->offset < iter->buf->size)); +} + +/** Advance `iter` forward one event. + * `iter` must be valid. + * @return True if `iter` is valid, otherwise false (reached end of buffer) */ +static inline bool +lv2_event_increment(LV2_Event_Iterator* iter) +{ + if (!lv2_event_is_valid(iter)) { + return false; + } + + LV2_Event* const ev = (LV2_Event*)(iter->buf->data + iter->offset); + + iter->offset += + lv2_event_pad_size((uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size)); + + return true; +} + +/** Dereference an event iterator (get the event currently pointed at). + * `iter` must be valid. + * `data` if non-NULL, will be set to point to the contents of the event + * returned. + * @return A Pointer to the event `iter` is currently pointing at, or NULL + * if the end of the buffer is reached (in which case `data` is + * also set to NULL). */ +static inline LV2_Event* +lv2_event_get(LV2_Event_Iterator* iter, uint8_t** data) +{ + if (!lv2_event_is_valid(iter)) { + return NULL; + } + + LV2_Event* const ev = (LV2_Event*)(iter->buf->data + iter->offset); + + if (data) { + *data = (uint8_t*)ev + sizeof(LV2_Event); + } + + return ev; +} + +/** Write an event at `iter`. + * The event (if any) pointed to by `iter` will be overwritten, and `iter` + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size, + const uint8_t* data) +{ + if (!iter->buf) { + return false; + } + + if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) { + return false; + } + + LV2_Event* const ev = (LV2_Event*)(iter->buf->data + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); + ++iter->buf->event_count; + + size = lv2_event_pad_size((uint16_t)(sizeof(LV2_Event) + size)); + iter->buf->size += size; + iter->offset += size; + + return true; +} + +/** Reserve space for an event in the buffer and return a pointer to + the memory where the caller can write the event data, or NULL if there + is not enough room in the buffer. */ +static inline uint8_t* +lv2_event_reserve(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size) +{ + const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size); + if (iter->buf->capacity - iter->buf->size < total_size) { + return NULL; + } + + LV2_Event* const ev = (LV2_Event*)(iter->buf->data + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + ++iter->buf->event_count; + + const uint16_t padded_size = lv2_event_pad_size(total_size); + iter->buf->size += padded_size; + iter->offset += padded_size; + + return (uint8_t*)ev + sizeof(LV2_Event); +} + +/** Write an event at `iter`. + * The event (if any) pointed to by `iter` will be overwritten, and `iter` + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write_event(LV2_Event_Iterator* iter, + const LV2_Event* ev, + const uint8_t* data) +{ + const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size); + if (iter->buf->capacity - iter->buf->size < total_size) { + return false; + } + + LV2_Event* const write_ev = (LV2_Event*)(iter->buf->data + iter->offset); + + *write_ev = *ev; + memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size); + ++iter->buf->event_count; + + const uint16_t padded_size = lv2_event_pad_size(total_size); + iter->buf->size += padded_size; + iter->offset += padded_size; + + return true; +} + +LV2_RESTORE_WARNINGS + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_EVENT_HELPERS_H */ diff --git a/include/lv2/event/event.h b/include/lv2/event/event.h new file mode 100644 index 0000000..045ac12 --- /dev/null +++ b/include/lv2/event/event.h @@ -0,0 +1,306 @@ +/* + Copyright 2008-2016 David Robillard <d@drobilla.net> + Copyright 2006-2007 Lars Luthman <lars.luthman@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. +*/ + +#ifndef LV2_EVENT_H +#define LV2_EVENT_H + +/** + @defgroup event Event + @ingroup lv2 + + Generic time-stamped events. + + See <http://lv2plug.in/ns/ext/event> for details. + + @{ +*/ + +// clang-format off + +#define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event" ///< http://lv2plug.in/ns/ext/event +#define LV2_EVENT_PREFIX LV2_EVENT_URI "#" ///< http://lv2plug.in/ns/ext/event# + +#define LV2_EVENT__Event LV2_EVENT_PREFIX "Event" ///< http://lv2plug.in/ns/ext/event#Event +#define LV2_EVENT__EventPort LV2_EVENT_PREFIX "EventPort" ///< http://lv2plug.in/ns/ext/event#EventPort +#define LV2_EVENT__FrameStamp LV2_EVENT_PREFIX "FrameStamp" ///< http://lv2plug.in/ns/ext/event#FrameStamp +#define LV2_EVENT__TimeStamp LV2_EVENT_PREFIX "TimeStamp" ///< http://lv2plug.in/ns/ext/event#TimeStamp +#define LV2_EVENT__generatesTimeStamp LV2_EVENT_PREFIX "generatesTimeStamp" ///< http://lv2plug.in/ns/ext/event#generatesTimeStamp +#define LV2_EVENT__generic LV2_EVENT_PREFIX "generic" ///< http://lv2plug.in/ns/ext/event#generic +#define LV2_EVENT__inheritsEvent LV2_EVENT_PREFIX "inheritsEvent" ///< http://lv2plug.in/ns/ext/event#inheritsEvent +#define LV2_EVENT__inheritsTimeStamp LV2_EVENT_PREFIX "inheritsTimeStamp" ///< http://lv2plug.in/ns/ext/event#inheritsTimeStamp +#define LV2_EVENT__supportsEvent LV2_EVENT_PREFIX "supportsEvent" ///< http://lv2plug.in/ns/ext/event#supportsEvent +#define LV2_EVENT__supportsTimeStamp LV2_EVENT_PREFIX "supportsTimeStamp" ///< http://lv2plug.in/ns/ext/event#supportsTimeStamp + +// clang-format on + +#define LV2_EVENT_AUDIO_STAMP 0 ///< Special timestamp type for audio frames + +#include "lv2/core/attributes.h" + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +LV2_DISABLE_DEPRECATION_WARNINGS + +/** + The best Pulses Per Quarter Note for tempo-based uint32_t timestamps. + Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisible + by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12. +*/ +LV2_DEPRECATED +static const uint32_t LV2_EVENT_PPQN = 3136573440U; + +/** + An LV2 event (header only). + + LV2 events are generic time-stamped containers for any type of event. + The type field defines the format of a given event's contents. + + This struct defines the header of an LV2 event. An LV2 event is a single + chunk of POD (plain old data), usually contained in a flat buffer (see + LV2_EventBuffer below). Unless a required feature says otherwise, hosts may + assume a deep copy of an LV2 event can be created safely using a simple: + + memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent) +*/ +LV2_DEPRECATED +typedef struct { + /** + The frames portion of timestamp. The units used here can optionally be + set for a port (with the lv2ev:timeUnits property), otherwise this is + audio frames, corresponding to the sample_count parameter of the LV2 run + method (frame 0 is the first frame for that call to run). + */ + uint32_t frames; + + /** + The sub-frames portion of timestamp. The units used here can optionally + be set for a port (with the lv2ev:timeUnits property), otherwise this is + 1/(2^32) of an audio frame. + */ + uint32_t subframes; + + /** + The type of this event, as a number which represents some URI + defining an event type. This value MUST be some value previously + returned from a call to the uri_to_id function defined in the LV2 + URI map extension (see lv2_uri_map.h). + There are special rules which must be followed depending on the type + of an event. If the plugin recognizes an event type, the definition + of that event type will describe how to interpret the event, and + any required behaviour. Otherwise, if the type is 0, this event is a + non-POD event and lv2_event_unref MUST be called if the event is + 'dropped' (see above). Even if the plugin does not understand an event, + it may pass the event through to an output by simply copying (and NOT + calling lv2_event_unref). These rules are designed to allow for generic + event handling plugins and large non-POD events, but with minimal hassle + on simple plugins that "don't care" about these more advanced features. + */ + uint16_t type; + + /** + The size of the data portion of this event in bytes, which immediately + follows. The header size (12 bytes) is not included in this value. + */ + uint16_t size; + + /* size bytes of data follow here */ +} LV2_Event; + +/** + A buffer of LV2 events (header only). + + Like events (which this contains) an event buffer is a single chunk of POD: + the entire buffer (including contents) can be copied with a single memcpy. + The first contained event begins sizeof(LV2_EventBuffer) bytes after the + start of this struct. + + After this header, the buffer contains an event header (defined by struct + LV2_Event), followed by that event's contents (padded to 64 bits), followed + by another header, etc: + + | | | | | | | + | | | | | | | | | | | | | | | | | | | | | | | | | + |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ... +*/ +LV2_DEPRECATED +typedef struct { + /** + The contents of the event buffer. This may or may not reside in the + same block of memory as this header, plugins must not assume either. + The host guarantees this points to at least capacity bytes of allocated + memory (though only size bytes of that are valid events). + */ + uint8_t* data; + + /** + The size of this event header in bytes (including everything). + + This is to allow for extending this header in the future without + breaking binary compatibility. Whenever this header is copied, + it MUST be done using this field (and NOT the sizeof this struct). + */ + uint16_t header_size; + + /** + The type of the time stamps for events in this buffer. + As a special exception, '0' always means audio frames and subframes + (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate. + + INPUTS: The host must set this field to the numeric ID of some URI + defining the meaning of the frames/subframes fields of contained events + (obtained by the LV2 URI Map uri_to_id function with the URI of this + extension as the 'map' argument, see lv2_uri_map.h). The host must + never pass a plugin a buffer which uses a stamp type the plugin does not + 'understand'. The value of this field must never change, except when + connect_port is called on the input port, at which time the host MUST + have set the stamp_type field to the value that will be used for all + subsequent run calls. + + OUTPUTS: The plugin may set this to any value that has been returned + from uri_to_id with the URI of this extension for a 'map' argument. + When connected to a buffer with connect_port, output ports MUST set this + field to the type of time stamp they will be writing. On any call to + connect_port on an event input port, the plugin may change this field on + any output port, it is the responsibility of the host to check if any of + these values have changed and act accordingly. + */ + uint16_t stamp_type; + + /** + The number of events in this buffer. + + INPUTS: The host must set this field to the number of events contained + in the data buffer before calling run(). The plugin must not change + this field. + + OUTPUTS: The plugin must set this field to the number of events it has + written to the buffer before returning from run(). Any initial value + should be ignored by the plugin. + */ + uint32_t event_count; + + /** + The size of the data buffer in bytes. + This is set by the host and must not be changed by the plugin. + The host is allowed to change this between run() calls. + */ + uint32_t capacity; + + /** + The size of the initial portion of the data buffer containing data. + + INPUTS: The host must set this field to the number of bytes used + by all events it has written to the buffer (including headers) + before calling the plugin's run(). + The plugin must not change this field. + + OUTPUTS: The plugin must set this field to the number of bytes + used by all events it has written to the buffer (including headers) + before returning from run(). + Any initial value should be ignored by the plugin. + */ + uint32_t size; +} LV2_Event_Buffer; + +/** + Opaque pointer to host data. +*/ +LV2_DEPRECATED +typedef void* LV2_Event_Callback_Data; + +/** + Non-POD events 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/event" + and data pointed to an instance of this struct. Note this feature + is not mandatory to support the event extension. +*/ +LV2_DEPRECATED +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_Event_Callback_Data callback_data; + + /** + Take a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. When receiving a non-POD event, the plugin already + has an implicit reference to the event. If the event is stored AND + passed to an output, lv2_event_ref MUST be called on that event. + If the event is only stored OR passed through, this is not necessary + (as the plugin already has 1 implicit reference). + + @param event An event received at an input that will not be copied to + an output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff the context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); + + /** + Drop a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. If the plugin does not pass the event through to + an output or store it internally somehow, it MUST call this function + on the event (more information on using non-POD events below). + + @param event An event received at an input that will not be copied to an + output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff the context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); +} LV2_Event_Feature; + +LV2_RESTORE_WARNINGS + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_EVENT_H */ diff --git a/include/lv2/instance-access/instance-access.h b/include/lv2/instance-access/instance-access.h new file mode 100644 index 0000000..2986f69 --- /dev/null +++ b/include/lv2/instance-access/instance-access.h @@ -0,0 +1,41 @@ +/* + Copyright 2008-2016 David Robillard <d@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. +*/ + +#ifndef LV2_INSTANCE_ACCESS_H +#define LV2_INSTANCE_ACCESS_H + +/** + @defgroup instance-access Instance Access + @ingroup lv2 + + Access to the LV2_Handle of a plugin for UIs. + + See <http://lv2plug.in/ns/ext/instance-access> for details. + + @{ +*/ + +// clang-format off + +#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access" ///< http://lv2plug.in/ns/ext/instance-access + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_INSTANCE_ACCESS_H */ diff --git a/include/lv2/log/log.h b/include/lv2/log/log.h new file mode 100644 index 0000000..cc62bef --- /dev/null +++ b/include/lv2/log/log.h @@ -0,0 +1,113 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_LOG_H +#define LV2_LOG_H + +/** + @defgroup log Log + @ingroup lv2 + + Interface for plugins to log via the host. + + See <http://lv2plug.in/ns/ext/log> for details. + + @{ +*/ + +// clang-format off + +#define LV2_LOG_URI "http://lv2plug.in/ns/ext/log" ///< http://lv2plug.in/ns/ext/log +#define LV2_LOG_PREFIX LV2_LOG_URI "#" ///< http://lv2plug.in/ns/ext/log# + +#define LV2_LOG__Entry LV2_LOG_PREFIX "Entry" ///< http://lv2plug.in/ns/ext/log#Entry +#define LV2_LOG__Error LV2_LOG_PREFIX "Error" ///< http://lv2plug.in/ns/ext/log#Error +#define LV2_LOG__Note LV2_LOG_PREFIX "Note" ///< http://lv2plug.in/ns/ext/log#Note +#define LV2_LOG__Trace LV2_LOG_PREFIX "Trace" ///< http://lv2plug.in/ns/ext/log#Trace +#define LV2_LOG__Warning LV2_LOG_PREFIX "Warning" ///< http://lv2plug.in/ns/ext/log#Warning +#define LV2_LOG__log LV2_LOG_PREFIX "log" ///< http://lv2plug.in/ns/ext/log#log + +// clang-format on + +#include "lv2/urid/urid.h" + +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond */ +#ifdef __GNUC__ +/** Allow type checking of printf-like functions. */ +# define LV2_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) +#else +# define LV2_LOG_FUNC(fmt, arg1) +#endif +/** @endcond */ + +/** + Opaque data to host data for LV2_Log_Log. +*/ +typedef void* LV2_Log_Handle; + +/** + Log feature (LV2_LOG__log) +*/ +typedef struct { + /** + Opaque pointer to host data. + + This MUST be passed to methods in this struct whenever they are called. + Otherwise, it must not be interpreted in any way. + */ + LV2_Log_Handle handle; + + /** + Log a message, passing format parameters directly. + + The API of this function matches that of the standard C printf function, + except for the addition of the first two parameters. This function may + be called from any non-realtime context, or from any context if `type` + is @ref LV2_LOG__Trace. + */ + LV2_LOG_FUNC(3, 4) + int (*printf)(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...); + + /** + Log a message, passing format parameters in a va_list. + + The API of this function matches that of the standard C vprintf + function, except for the addition of the first two parameters. This + function may be called from any non-realtime context, or from any + context if `type` is @ref LV2_LOG__Trace. + */ + LV2_LOG_FUNC(3, 0) + int (*vprintf)(LV2_Log_Handle handle, + LV2_URID type, + const char* fmt, + va_list ap); +} LV2_Log_Log; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_LOG_H */ diff --git a/include/lv2/log/logger.h b/include/lv2/log/logger.h new file mode 100644 index 0000000..d6919a2 --- /dev/null +++ b/include/lv2/log/logger.h @@ -0,0 +1,157 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_ATOM_LOGGER_H +#define LV2_ATOM_LOGGER_H + +/** + @defgroup logger Logger + @ingroup log + + Convenience API for easy logging in plugin code. This API provides simple + wrappers for logging from a plugin, which automatically fall back to + printing to stderr if host support is unavailable. + + @{ +*/ + +#include "lv2/log/log.h" +#include "lv2/urid/urid.h" + +#include <stdarg.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Logger convenience API state. +*/ +typedef struct { + LV2_Log_Log* log; + + LV2_URID Error; + LV2_URID Note; + LV2_URID Trace; + LV2_URID Warning; +} LV2_Log_Logger; + +/** + Set `map` as the URI map for `logger`. + + This affects the message type URIDs (Error, Warning, etc) which are passed + to the log's print functions. +*/ +static inline void +lv2_log_logger_set_map(LV2_Log_Logger* logger, LV2_URID_Map* map) +{ + if (map) { + logger->Error = map->map(map->handle, LV2_LOG__Error); + logger->Note = map->map(map->handle, LV2_LOG__Note); + logger->Trace = map->map(map->handle, LV2_LOG__Trace); + logger->Warning = map->map(map->handle, LV2_LOG__Warning); + } else { + logger->Error = logger->Note = logger->Trace = logger->Warning = 0; + } +} + +/** + Initialise `logger`. + + URIs will be mapped using `map` and stored, a reference to `map` itself is + not held. Both `map` and `log` may be NULL when unsupported by the host, + in which case the implementation will fall back to printing to stderr. +*/ +static inline void +lv2_log_logger_init(LV2_Log_Logger* logger, LV2_URID_Map* map, LV2_Log_Log* log) +{ + logger->log = log; + lv2_log_logger_set_map(logger, map); +} + +/** + Log a message to the host, or stderr if support is unavailable. +*/ +LV2_LOG_FUNC(3, 0) +static inline int +lv2_log_vprintf(LV2_Log_Logger* logger, + LV2_URID type, + const char* fmt, + va_list args) +{ + return ((logger && logger->log) + ? logger->log->vprintf(logger->log->handle, type, fmt, args) + : vfprintf(stderr, fmt, args)); +} + +/** Log an error via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_error(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Error, fmt, args); + va_end(args); + return ret; +} + +/** Log a note via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_note(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Note, fmt, args); + va_end(args); + return ret; +} + +/** Log a trace via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_trace(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Trace, fmt, args); + va_end(args); + return ret; +} + +/** Log a warning via lv2_log_vprintf(). */ +LV2_LOG_FUNC(2, 3) +static inline int +lv2_log_warning(LV2_Log_Logger* logger, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + const int ret = lv2_log_vprintf(logger, logger->Warning, fmt, args); + va_end(args); + return ret; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_LOG_LOGGER_H */ diff --git a/include/lv2/midi/midi.h b/include/lv2/midi/midi.h new file mode 100644 index 0000000..f7e0500 --- /dev/null +++ b/include/lv2/midi/midi.h @@ -0,0 +1,248 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_MIDI_H +#define LV2_MIDI_H + +/** + @defgroup midi MIDI + @ingroup lv2 + + Definitions of standard MIDI messages. + + See <http://lv2plug.in/ns/ext/midi> for details. + + @{ +*/ + +#include <stdbool.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// clang-format off + +#define LV2_MIDI_URI "http://lv2plug.in/ns/ext/midi" ///< http://lv2plug.in/ns/ext/midi +#define LV2_MIDI_PREFIX LV2_MIDI_URI "#" ///< http://lv2plug.in/ns/ext/midi# + +#define LV2_MIDI__ActiveSense LV2_MIDI_PREFIX "ActiveSense" ///< http://lv2plug.in/ns/ext/midi#ActiveSense +#define LV2_MIDI__Aftertouch LV2_MIDI_PREFIX "Aftertouch" ///< http://lv2plug.in/ns/ext/midi#Aftertouch +#define LV2_MIDI__Bender LV2_MIDI_PREFIX "Bender" ///< http://lv2plug.in/ns/ext/midi#Bender +#define LV2_MIDI__ChannelPressure LV2_MIDI_PREFIX "ChannelPressure" ///< http://lv2plug.in/ns/ext/midi#ChannelPressure +#define LV2_MIDI__Chunk LV2_MIDI_PREFIX "Chunk" ///< http://lv2plug.in/ns/ext/midi#Chunk +#define LV2_MIDI__Clock LV2_MIDI_PREFIX "Clock" ///< http://lv2plug.in/ns/ext/midi#Clock +#define LV2_MIDI__Continue LV2_MIDI_PREFIX "Continue" ///< http://lv2plug.in/ns/ext/midi#Continue +#define LV2_MIDI__Controller LV2_MIDI_PREFIX "Controller" ///< http://lv2plug.in/ns/ext/midi#Controller +#define LV2_MIDI__MidiEvent LV2_MIDI_PREFIX "MidiEvent" ///< http://lv2plug.in/ns/ext/midi#MidiEvent +#define LV2_MIDI__NoteOff LV2_MIDI_PREFIX "NoteOff" ///< http://lv2plug.in/ns/ext/midi#NoteOff +#define LV2_MIDI__NoteOn LV2_MIDI_PREFIX "NoteOn" ///< http://lv2plug.in/ns/ext/midi#NoteOn +#define LV2_MIDI__ProgramChange LV2_MIDI_PREFIX "ProgramChange" ///< http://lv2plug.in/ns/ext/midi#ProgramChange +#define LV2_MIDI__QuarterFrame LV2_MIDI_PREFIX "QuarterFrame" ///< http://lv2plug.in/ns/ext/midi#QuarterFrame +#define LV2_MIDI__Reset LV2_MIDI_PREFIX "Reset" ///< http://lv2plug.in/ns/ext/midi#Reset +#define LV2_MIDI__SongPosition LV2_MIDI_PREFIX "SongPosition" ///< http://lv2plug.in/ns/ext/midi#SongPosition +#define LV2_MIDI__SongSelect LV2_MIDI_PREFIX "SongSelect" ///< http://lv2plug.in/ns/ext/midi#SongSelect +#define LV2_MIDI__Start LV2_MIDI_PREFIX "Start" ///< http://lv2plug.in/ns/ext/midi#Start +#define LV2_MIDI__Stop LV2_MIDI_PREFIX "Stop" ///< http://lv2plug.in/ns/ext/midi#Stop +#define LV2_MIDI__SystemCommon LV2_MIDI_PREFIX "SystemCommon" ///< http://lv2plug.in/ns/ext/midi#SystemCommon +#define LV2_MIDI__SystemExclusive LV2_MIDI_PREFIX "SystemExclusive" ///< http://lv2plug.in/ns/ext/midi#SystemExclusive +#define LV2_MIDI__SystemMessage LV2_MIDI_PREFIX "SystemMessage" ///< http://lv2plug.in/ns/ext/midi#SystemMessage +#define LV2_MIDI__SystemRealtime LV2_MIDI_PREFIX "SystemRealtime" ///< http://lv2plug.in/ns/ext/midi#SystemRealtime +#define LV2_MIDI__Tick LV2_MIDI_PREFIX "Tick" ///< http://lv2plug.in/ns/ext/midi#Tick +#define LV2_MIDI__TuneRequest LV2_MIDI_PREFIX "TuneRequest" ///< http://lv2plug.in/ns/ext/midi#TuneRequest +#define LV2_MIDI__VoiceMessage LV2_MIDI_PREFIX "VoiceMessage" ///< http://lv2plug.in/ns/ext/midi#VoiceMessage +#define LV2_MIDI__benderValue LV2_MIDI_PREFIX "benderValue" ///< http://lv2plug.in/ns/ext/midi#benderValue +#define LV2_MIDI__binding LV2_MIDI_PREFIX "binding" ///< http://lv2plug.in/ns/ext/midi#binding +#define LV2_MIDI__byteNumber LV2_MIDI_PREFIX "byteNumber" ///< http://lv2plug.in/ns/ext/midi#byteNumber +#define LV2_MIDI__channel LV2_MIDI_PREFIX "channel" ///< http://lv2plug.in/ns/ext/midi#channel +#define LV2_MIDI__chunk LV2_MIDI_PREFIX "chunk" ///< http://lv2plug.in/ns/ext/midi#chunk +#define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber" ///< http://lv2plug.in/ns/ext/midi#controllerNumber +#define LV2_MIDI__controllerValue LV2_MIDI_PREFIX "controllerValue" ///< http://lv2plug.in/ns/ext/midi#controllerValue +#define LV2_MIDI__noteNumber LV2_MIDI_PREFIX "noteNumber" ///< http://lv2plug.in/ns/ext/midi#noteNumber +#define LV2_MIDI__pressure LV2_MIDI_PREFIX "pressure" ///< http://lv2plug.in/ns/ext/midi#pressure +#define LV2_MIDI__programNumber LV2_MIDI_PREFIX "programNumber" ///< http://lv2plug.in/ns/ext/midi#programNumber +#define LV2_MIDI__property LV2_MIDI_PREFIX "property" ///< http://lv2plug.in/ns/ext/midi#property +#define LV2_MIDI__songNumber LV2_MIDI_PREFIX "songNumber" ///< http://lv2plug.in/ns/ext/midi#songNumber +#define LV2_MIDI__songPosition LV2_MIDI_PREFIX "songPosition" ///< http://lv2plug.in/ns/ext/midi#songPosition +#define LV2_MIDI__status LV2_MIDI_PREFIX "status" ///< http://lv2plug.in/ns/ext/midi#status +#define LV2_MIDI__statusMask LV2_MIDI_PREFIX "statusMask" ///< http://lv2plug.in/ns/ext/midi#statusMask +#define LV2_MIDI__velocity LV2_MIDI_PREFIX "velocity" ///< http://lv2plug.in/ns/ext/midi#velocity + +// clang-format on + +/** + MIDI Message Type. + + This includes both voice messages (which have a channel) and system messages + (which do not), as well as a sentinel value for invalid messages. To get + the type of a message suitable for use in a switch statement, use + lv2_midi_get_type() on the status byte. +*/ +typedef enum { + LV2_MIDI_MSG_INVALID = 0, /**< Invalid Message */ + LV2_MIDI_MSG_NOTE_OFF = 0x80, /**< Note Off */ + LV2_MIDI_MSG_NOTE_ON = 0x90, /**< Note On */ + LV2_MIDI_MSG_NOTE_PRESSURE = 0xA0, /**< Note Pressure */ + LV2_MIDI_MSG_CONTROLLER = 0xB0, /**< Controller */ + LV2_MIDI_MSG_PGM_CHANGE = 0xC0, /**< Program Change */ + LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0, /**< Channel Pressure */ + LV2_MIDI_MSG_BENDER = 0xE0, /**< Pitch Bender */ + LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0, /**< System Exclusive Begin */ + LV2_MIDI_MSG_MTC_QUARTER = 0xF1, /**< MTC Quarter Frame */ + LV2_MIDI_MSG_SONG_POS = 0xF2, /**< Song Position */ + LV2_MIDI_MSG_SONG_SELECT = 0xF3, /**< Song Select */ + LV2_MIDI_MSG_TUNE_REQUEST = 0xF6, /**< Tune Request */ + LV2_MIDI_MSG_CLOCK = 0xF8, /**< Clock */ + LV2_MIDI_MSG_START = 0xFA, /**< Start */ + LV2_MIDI_MSG_CONTINUE = 0xFB, /**< Continue */ + LV2_MIDI_MSG_STOP = 0xFC, /**< Stop */ + LV2_MIDI_MSG_ACTIVE_SENSE = 0xFE, /**< Active Sensing */ + LV2_MIDI_MSG_RESET = 0xFF /**< Reset */ +} LV2_Midi_Message_Type; + +/** + Standard MIDI Controller Numbers. +*/ +typedef enum { + LV2_MIDI_CTL_MSB_BANK = 0x00, /**< Bank Selection */ + LV2_MIDI_CTL_MSB_MODWHEEL = 0x01, /**< Modulation */ + LV2_MIDI_CTL_MSB_BREATH = 0x02, /**< Breath */ + LV2_MIDI_CTL_MSB_FOOT = 0x04, /**< Foot */ + LV2_MIDI_CTL_MSB_PORTAMENTO_TIME = 0x05, /**< Portamento Time */ + LV2_MIDI_CTL_MSB_DATA_ENTRY = 0x06, /**< Data Entry */ + LV2_MIDI_CTL_MSB_MAIN_VOLUME = 0x07, /**< Main Volume */ + LV2_MIDI_CTL_MSB_BALANCE = 0x08, /**< Balance */ + LV2_MIDI_CTL_MSB_PAN = 0x0A, /**< Panpot */ + LV2_MIDI_CTL_MSB_EXPRESSION = 0x0B, /**< Expression */ + LV2_MIDI_CTL_MSB_EFFECT1 = 0x0C, /**< Effect1 */ + LV2_MIDI_CTL_MSB_EFFECT2 = 0x0D, /**< Effect2 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, /**< General Purpose 1 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, /**< General Purpose 2 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, /**< General Purpose 3 */ + LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, /**< General Purpose 4 */ + LV2_MIDI_CTL_LSB_BANK = 0x20, /**< Bank Selection */ + LV2_MIDI_CTL_LSB_MODWHEEL = 0x21, /**< Modulation */ + LV2_MIDI_CTL_LSB_BREATH = 0x22, /**< Breath */ + LV2_MIDI_CTL_LSB_FOOT = 0x24, /**< Foot */ + LV2_MIDI_CTL_LSB_PORTAMENTO_TIME = 0x25, /**< Portamento Time */ + LV2_MIDI_CTL_LSB_DATA_ENTRY = 0x26, /**< Data Entry */ + LV2_MIDI_CTL_LSB_MAIN_VOLUME = 0x27, /**< Main Volume */ + LV2_MIDI_CTL_LSB_BALANCE = 0x28, /**< Balance */ + LV2_MIDI_CTL_LSB_PAN = 0x2A, /**< Panpot */ + LV2_MIDI_CTL_LSB_EXPRESSION = 0x2B, /**< Expression */ + LV2_MIDI_CTL_LSB_EFFECT1 = 0x2C, /**< Effect1 */ + LV2_MIDI_CTL_LSB_EFFECT2 = 0x2D, /**< Effect2 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, /**< General Purpose 1 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, /**< General Purpose 2 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, /**< General Purpose 3 */ + LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, /**< General Purpose 4 */ + LV2_MIDI_CTL_SUSTAIN = 0x40, /**< Sustain Pedal */ + LV2_MIDI_CTL_PORTAMENTO = 0x41, /**< Portamento */ + LV2_MIDI_CTL_SOSTENUTO = 0x42, /**< Sostenuto */ + LV2_MIDI_CTL_SOFT_PEDAL = 0x43, /**< Soft Pedal */ + LV2_MIDI_CTL_LEGATO_FOOTSWITCH = 0x44, /**< Legato Foot Switch */ + LV2_MIDI_CTL_HOLD2 = 0x45, /**< Hold2 */ + LV2_MIDI_CTL_SC1_SOUND_VARIATION = 0x46, /**< SC1 Sound Variation */ + LV2_MIDI_CTL_SC2_TIMBRE = 0x47, /**< SC2 Timbre */ + LV2_MIDI_CTL_SC3_RELEASE_TIME = 0x48, /**< SC3 Release Time */ + LV2_MIDI_CTL_SC4_ATTACK_TIME = 0x49, /**< SC4 Attack Time */ + LV2_MIDI_CTL_SC5_BRIGHTNESS = 0x4A, /**< SC5 Brightness */ + LV2_MIDI_CTL_SC6 = 0x4B, /**< SC6 */ + LV2_MIDI_CTL_SC7 = 0x4C, /**< SC7 */ + LV2_MIDI_CTL_SC8 = 0x4D, /**< SC8 */ + LV2_MIDI_CTL_SC9 = 0x4E, /**< SC9 */ + LV2_MIDI_CTL_SC10 = 0x4F, /**< SC10 */ + LV2_MIDI_CTL_GENERAL_PURPOSE5 = 0x50, /**< General Purpose 5 */ + LV2_MIDI_CTL_GENERAL_PURPOSE6 = 0x51, /**< General Purpose 6 */ + LV2_MIDI_CTL_GENERAL_PURPOSE7 = 0x52, /**< General Purpose 7 */ + LV2_MIDI_CTL_GENERAL_PURPOSE8 = 0x53, /**< General Purpose 8 */ + LV2_MIDI_CTL_PORTAMENTO_CONTROL = 0x54, /**< Portamento Control */ + LV2_MIDI_CTL_E1_REVERB_DEPTH = 0x5B, /**< E1 Reverb Depth */ + LV2_MIDI_CTL_E2_TREMOLO_DEPTH = 0x5C, /**< E2 Tremolo Depth */ + LV2_MIDI_CTL_E3_CHORUS_DEPTH = 0x5D, /**< E3 Chorus Depth */ + LV2_MIDI_CTL_E4_DETUNE_DEPTH = 0x5E, /**< E4 Detune Depth */ + LV2_MIDI_CTL_E5_PHASER_DEPTH = 0x5F, /**< E5 Phaser Depth */ + LV2_MIDI_CTL_DATA_INCREMENT = 0x60, /**< Data Increment */ + LV2_MIDI_CTL_DATA_DECREMENT = 0x61, /**< Data Decrement */ + LV2_MIDI_CTL_NRPN_LSB = 0x62, /**< Non-registered Parameter Number */ + LV2_MIDI_CTL_NRPN_MSB = 0x63, /**< Non-registered Parameter Number */ + LV2_MIDI_CTL_RPN_LSB = 0x64, /**< Registered Parameter Number */ + LV2_MIDI_CTL_RPN_MSB = 0x65, /**< Registered Parameter Number */ + LV2_MIDI_CTL_ALL_SOUNDS_OFF = 0x78, /**< All Sounds Off */ + LV2_MIDI_CTL_RESET_CONTROLLERS = 0x79, /**< Reset Controllers */ + LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A, /**< Local Control Switch */ + LV2_MIDI_CTL_ALL_NOTES_OFF = 0x7B, /**< All Notes Off */ + LV2_MIDI_CTL_OMNI_OFF = 0x7C, /**< Omni Off */ + LV2_MIDI_CTL_OMNI_ON = 0x7D, /**< Omni On */ + LV2_MIDI_CTL_MONO1 = 0x7E, /**< Mono1 */ + LV2_MIDI_CTL_MONO2 = 0x7F /**< Mono2 */ +} LV2_Midi_Controller; + +/** + Return true iff `msg` is a MIDI voice message (which has a channel). +*/ +static inline bool +lv2_midi_is_voice_message(const uint8_t* msg) +{ + return msg[0] >= 0x80 && msg[0] < 0xF0; +} + +/** + Return true iff `msg` is a MIDI system message (which has no channel). +*/ +static inline bool +lv2_midi_is_system_message(const uint8_t* msg) +{ + switch (msg[0]) { + case 0xF4: + case 0xF5: + case 0xF7: + case 0xF9: + case 0xFD: + return false; + default: + return (msg[0] & 0xF0u) == 0xF0u; + } +} + +/** + Return the type of a MIDI message. + @param msg Pointer to the start (status byte) of a MIDI message. +*/ +static inline LV2_Midi_Message_Type +lv2_midi_message_type(const uint8_t* msg) +{ + if (lv2_midi_is_voice_message(msg)) { + return (LV2_Midi_Message_Type)(msg[0] & 0xF0u); + } + + if (lv2_midi_is_system_message(msg)) { + return (LV2_Midi_Message_Type)msg[0]; + } + + return LV2_MIDI_MSG_INVALID; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_MIDI_H */ diff --git a/include/lv2/morph/morph.h b/include/lv2/morph/morph.h new file mode 100644 index 0000000..370937a --- /dev/null +++ b/include/lv2/morph/morph.h @@ -0,0 +1,48 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_MORPH_H +#define LV2_MORPH_H + +/** + @defgroup morph Morph + @ingroup lv2 + + Ports that can dynamically change type. + + See <http://lv2plug.in/ns/ext/morph> for details. + + @{ +*/ + +// clang-format off + +#define LV2_MORPH_URI "http://lv2plug.in/ns/ext/morph" ///< http://lv2plug.in/ns/ext/morph +#define LV2_MORPH_PREFIX LV2_MORPH_URI "#" ///< http://lv2plug.in/ns/ext/morph# + +#define LV2_MORPH__AutoMorphPort LV2_MORPH_PREFIX "AutoMorphPort" ///< http://lv2plug.in/ns/ext/morph#AutoMorphPort +#define LV2_MORPH__MorphPort LV2_MORPH_PREFIX "MorphPort" ///< http://lv2plug.in/ns/ext/morph#MorphPort +#define LV2_MORPH__interface LV2_MORPH_PREFIX "interface" ///< http://lv2plug.in/ns/ext/morph#interface +#define LV2_MORPH__supportsType LV2_MORPH_PREFIX "supportsType" ///< http://lv2plug.in/ns/ext/morph#supportsType +#define LV2_MORPH__currentType LV2_MORPH_PREFIX "currentType" ///< http://lv2plug.in/ns/ext/morph#currentType + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_MORPH_H */ diff --git a/include/lv2/options/options.h b/include/lv2/options/options.h new file mode 100644 index 0000000..06e5db4 --- /dev/null +++ b/include/lv2/options/options.h @@ -0,0 +1,149 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_OPTIONS_H +#define LV2_OPTIONS_H + +/** + @defgroup options Options + @ingroup lv2 + + Instantiation time options. + + See <http://lv2plug.in/ns/ext/options> for details. + + @{ +*/ + +#include "lv2/core/lv2.h" +#include "lv2/urid/urid.h" + +#include <stdint.h> + +// clang-format off + +#define LV2_OPTIONS_URI "http://lv2plug.in/ns/ext/options" ///< http://lv2plug.in/ns/ext/options +#define LV2_OPTIONS_PREFIX LV2_OPTIONS_URI "#" ///< http://lv2plug.in/ns/ext/options# + +#define LV2_OPTIONS__Option LV2_OPTIONS_PREFIX "Option" ///< http://lv2plug.in/ns/ext/options#Option +#define LV2_OPTIONS__interface LV2_OPTIONS_PREFIX "interface" ///< http://lv2plug.in/ns/ext/options#interface +#define LV2_OPTIONS__options LV2_OPTIONS_PREFIX "options" ///< http://lv2plug.in/ns/ext/options#options +#define LV2_OPTIONS__requiredOption LV2_OPTIONS_PREFIX "requiredOption" ///< http://lv2plug.in/ns/ext/options#requiredOption +#define LV2_OPTIONS__supportedOption LV2_OPTIONS_PREFIX "supportedOption" ///< http://lv2plug.in/ns/ext/options#supportedOption + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +/** + The context of an Option, which defines the subject it applies to. +*/ +typedef enum { + /** + This option applies to the instance itself. The subject must be + ignored. + */ + LV2_OPTIONS_INSTANCE, + + /** + This option applies to some named resource. The subject is a URI mapped + to an integer (a LV2_URID, like the key) + */ + LV2_OPTIONS_RESOURCE, + + /** + This option applies to some blank node. The subject is a blank node + identifier, which is valid only within the current local scope. + */ + LV2_OPTIONS_BLANK, + + /** + This option applies to a port on the instance. The subject is the + port's index. + */ + LV2_OPTIONS_PORT +} LV2_Options_Context; + +/** + An option. + + This is a property with a subject, also known as a triple or statement. + + This struct is useful anywhere a statement needs to be passed where no + memory ownership issues are present (since the value is a const pointer). + + Options can be passed to an instance via the feature LV2_OPTIONS__options + with data pointed to an array of options terminated by a zeroed option, or + accessed/manipulated using LV2_Options_Interface. +*/ +typedef struct { + LV2_Options_Context context; /**< Context (type of subject). */ + uint32_t subject; /**< Subject. */ + LV2_URID key; /**< Key (property). */ + uint32_t size; /**< Size of value in bytes. */ + LV2_URID type; /**< Type of value (datatype). */ + const void* value; /**< Pointer to value (object). */ +} LV2_Options_Option; + +/** A status code for option functions. */ +typedef enum { + LV2_OPTIONS_SUCCESS = 0u, /**< Completed successfully. */ + LV2_OPTIONS_ERR_UNKNOWN = 1u, /**< Unknown error. */ + LV2_OPTIONS_ERR_BAD_SUBJECT = 1u << 1u, /**< Invalid/unsupported subject. */ + LV2_OPTIONS_ERR_BAD_KEY = 1u << 2u, /**< Invalid/unsupported key. */ + LV2_OPTIONS_ERR_BAD_VALUE = 1u << 3u /**< Invalid/unsupported value. */ +} LV2_Options_Status; + +/** + Interface for dynamically setting options (LV2_OPTIONS__interface). +*/ +typedef struct { + /** + Get the given options. + + Each element of the passed options array MUST have type, subject, and + key set. All other fields (size, type, value) MUST be initialised to + zero, and are set to the option value if such an option is found. + + This function is in the "instantiation" LV2 threading class, so no other + instance functions may be called concurrently. + + @return Bitwise OR of LV2_Options_Status values. + */ + uint32_t (*get)(LV2_Handle instance, LV2_Options_Option* options); + + /** + Set the given options. + + This function is in the "instantiation" LV2 threading class, so no other + instance functions may be called concurrently. + + @return Bitwise OR of LV2_Options_Status values. + */ + uint32_t (*set)(LV2_Handle instance, const LV2_Options_Option* options); +} LV2_Options_Interface; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_OPTIONS_H */ diff --git a/include/lv2/parameters/parameters.h b/include/lv2/parameters/parameters.h new file mode 100644 index 0000000..66a7561 --- /dev/null +++ b/include/lv2/parameters/parameters.h @@ -0,0 +1,68 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_PARAMETERS_H +#define LV2_PARAMETERS_H + +/** + @defgroup parameters Parameters + @ingroup lv2 + + Common parameters for audio processing. + + See <http://lv2plug.in/ns/ext/parameters> for details. + + @{ +*/ + +// clang-format off + +#define LV2_PARAMETERS_URI "http://lv2plug.in/ns/ext/parameters" ///< http://lv2plug.in/ns/ext/parameters +#define LV2_PARAMETERS_PREFIX LV2_PARAMETERS_URI "#" ///< http://lv2plug.in/ns/ext/parameters# + +#define LV2_PARAMETERS__CompressorControls LV2_PARAMETERS_PREFIX "CompressorControls" ///< http://lv2plug.in/ns/ext/parameters#CompressorControls +#define LV2_PARAMETERS__ControlGroup LV2_PARAMETERS_PREFIX "ControlGroup" ///< http://lv2plug.in/ns/ext/parameters#ControlGroup +#define LV2_PARAMETERS__EnvelopeControls LV2_PARAMETERS_PREFIX "EnvelopeControls" ///< http://lv2plug.in/ns/ext/parameters#EnvelopeControls +#define LV2_PARAMETERS__FilterControls LV2_PARAMETERS_PREFIX "FilterControls" ///< http://lv2plug.in/ns/ext/parameters#FilterControls +#define LV2_PARAMETERS__OscillatorControls LV2_PARAMETERS_PREFIX "OscillatorControls" ///< http://lv2plug.in/ns/ext/parameters#OscillatorControls +#define LV2_PARAMETERS__amplitude LV2_PARAMETERS_PREFIX "amplitude" ///< http://lv2plug.in/ns/ext/parameters#amplitude +#define LV2_PARAMETERS__attack LV2_PARAMETERS_PREFIX "attack" ///< http://lv2plug.in/ns/ext/parameters#attack +#define LV2_PARAMETERS__bypass LV2_PARAMETERS_PREFIX "bypass" ///< http://lv2plug.in/ns/ext/parameters#bypass +#define LV2_PARAMETERS__cutoffFrequency LV2_PARAMETERS_PREFIX "cutoffFrequency" ///< http://lv2plug.in/ns/ext/parameters#cutoffFrequency +#define LV2_PARAMETERS__decay LV2_PARAMETERS_PREFIX "decay" ///< http://lv2plug.in/ns/ext/parameters#decay +#define LV2_PARAMETERS__delay LV2_PARAMETERS_PREFIX "delay" ///< http://lv2plug.in/ns/ext/parameters#delay +#define LV2_PARAMETERS__dryLevel LV2_PARAMETERS_PREFIX "dryLevel" ///< http://lv2plug.in/ns/ext/parameters#dryLevel +#define LV2_PARAMETERS__frequency LV2_PARAMETERS_PREFIX "frequency" ///< http://lv2plug.in/ns/ext/parameters#frequency +#define LV2_PARAMETERS__gain LV2_PARAMETERS_PREFIX "gain" ///< http://lv2plug.in/ns/ext/parameters#gain +#define LV2_PARAMETERS__hold LV2_PARAMETERS_PREFIX "hold" ///< http://lv2plug.in/ns/ext/parameters#hold +#define LV2_PARAMETERS__pulseWidth LV2_PARAMETERS_PREFIX "pulseWidth" ///< http://lv2plug.in/ns/ext/parameters#pulseWidth +#define LV2_PARAMETERS__ratio LV2_PARAMETERS_PREFIX "ratio" ///< http://lv2plug.in/ns/ext/parameters#ratio +#define LV2_PARAMETERS__release LV2_PARAMETERS_PREFIX "release" ///< http://lv2plug.in/ns/ext/parameters#release +#define LV2_PARAMETERS__resonance LV2_PARAMETERS_PREFIX "resonance" ///< http://lv2plug.in/ns/ext/parameters#resonance +#define LV2_PARAMETERS__sampleRate LV2_PARAMETERS_PREFIX "sampleRate" ///< http://lv2plug.in/ns/ext/parameters#sampleRate +#define LV2_PARAMETERS__sustain LV2_PARAMETERS_PREFIX "sustain" ///< http://lv2plug.in/ns/ext/parameters#sustain +#define LV2_PARAMETERS__threshold LV2_PARAMETERS_PREFIX "threshold" ///< http://lv2plug.in/ns/ext/parameters#threshold +#define LV2_PARAMETERS__waveform LV2_PARAMETERS_PREFIX "waveform" ///< http://lv2plug.in/ns/ext/parameters#waveform +#define LV2_PARAMETERS__wetDryRatio LV2_PARAMETERS_PREFIX "wetDryRatio" ///< http://lv2plug.in/ns/ext/parameters#wetDryRatio +#define LV2_PARAMETERS__wetLevel LV2_PARAMETERS_PREFIX "wetLevel" ///< http://lv2plug.in/ns/ext/parameters#wetLevel + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_PARAMETERS_H */ diff --git a/include/lv2/patch/patch.h b/include/lv2/patch/patch.h new file mode 100644 index 0000000..4db2abb --- /dev/null +++ b/include/lv2/patch/patch.h @@ -0,0 +1,73 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_PATCH_H +#define LV2_PATCH_H + +/** + @defgroup patch Patch + @ingroup lv2 + + Messages for accessing and manipulating properties. + + Note the patch extension is purely data, this header merely defines URIs for + convenience. + + See <http://lv2plug.in/ns/ext/patch> for details. + + @{ +*/ + +// clang-format off + +#define LV2_PATCH_URI "http://lv2plug.in/ns/ext/patch" ///< http://lv2plug.in/ns/ext/patch +#define LV2_PATCH_PREFIX LV2_PATCH_URI "#" ///< http://lv2plug.in/ns/ext/patch# + +#define LV2_PATCH__Ack LV2_PATCH_PREFIX "Ack" ///< http://lv2plug.in/ns/ext/patch#Ack +#define LV2_PATCH__Delete LV2_PATCH_PREFIX "Delete" ///< http://lv2plug.in/ns/ext/patch#Delete +#define LV2_PATCH__Copy LV2_PATCH_PREFIX "Copy" ///< http://lv2plug.in/ns/ext/patch#Copy +#define LV2_PATCH__Error LV2_PATCH_PREFIX "Error" ///< http://lv2plug.in/ns/ext/patch#Error +#define LV2_PATCH__Get LV2_PATCH_PREFIX "Get" ///< http://lv2plug.in/ns/ext/patch#Get +#define LV2_PATCH__Message LV2_PATCH_PREFIX "Message" ///< http://lv2plug.in/ns/ext/patch#Message +#define LV2_PATCH__Move LV2_PATCH_PREFIX "Move" ///< http://lv2plug.in/ns/ext/patch#Move +#define LV2_PATCH__Patch LV2_PATCH_PREFIX "Patch" ///< http://lv2plug.in/ns/ext/patch#Patch +#define LV2_PATCH__Post LV2_PATCH_PREFIX "Post" ///< http://lv2plug.in/ns/ext/patch#Post +#define LV2_PATCH__Put LV2_PATCH_PREFIX "Put" ///< http://lv2plug.in/ns/ext/patch#Put +#define LV2_PATCH__Request LV2_PATCH_PREFIX "Request" ///< http://lv2plug.in/ns/ext/patch#Request +#define LV2_PATCH__Response LV2_PATCH_PREFIX "Response" ///< http://lv2plug.in/ns/ext/patch#Response +#define LV2_PATCH__Set LV2_PATCH_PREFIX "Set" ///< http://lv2plug.in/ns/ext/patch#Set +#define LV2_PATCH__accept LV2_PATCH_PREFIX "accept" ///< http://lv2plug.in/ns/ext/patch#accept +#define LV2_PATCH__add LV2_PATCH_PREFIX "add" ///< http://lv2plug.in/ns/ext/patch#add +#define LV2_PATCH__body LV2_PATCH_PREFIX "body" ///< http://lv2plug.in/ns/ext/patch#body +#define LV2_PATCH__context LV2_PATCH_PREFIX "context" ///< http://lv2plug.in/ns/ext/patch#context +#define LV2_PATCH__destination LV2_PATCH_PREFIX "destination" ///< http://lv2plug.in/ns/ext/patch#destination +#define LV2_PATCH__property LV2_PATCH_PREFIX "property" ///< http://lv2plug.in/ns/ext/patch#property +#define LV2_PATCH__readable LV2_PATCH_PREFIX "readable" ///< http://lv2plug.in/ns/ext/patch#readable +#define LV2_PATCH__remove LV2_PATCH_PREFIX "remove" ///< http://lv2plug.in/ns/ext/patch#remove +#define LV2_PATCH__request LV2_PATCH_PREFIX "request" ///< http://lv2plug.in/ns/ext/patch#request +#define LV2_PATCH__subject LV2_PATCH_PREFIX "subject" ///< http://lv2plug.in/ns/ext/patch#subject +#define LV2_PATCH__sequenceNumber LV2_PATCH_PREFIX "sequenceNumber" ///< http://lv2plug.in/ns/ext/patch#sequenceNumber +#define LV2_PATCH__value LV2_PATCH_PREFIX "value" ///< http://lv2plug.in/ns/ext/patch#value +#define LV2_PATCH__wildcard LV2_PATCH_PREFIX "wildcard" ///< http://lv2plug.in/ns/ext/patch#wildcard +#define LV2_PATCH__writable LV2_PATCH_PREFIX "writable" ///< http://lv2plug.in/ns/ext/patch#writable + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_PATCH_H */ diff --git a/include/lv2/port-groups/port-groups.h b/include/lv2/port-groups/port-groups.h new file mode 100644 index 0000000..0ff25c7 --- /dev/null +++ b/include/lv2/port-groups/port-groups.h @@ -0,0 +1,77 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_PORT_GROUPS_H +#define LV2_PORT_GROUPS_H + +/** + @defgroup port-groups Port Groups + @ingroup lv2 + + Multi-channel groups of LV2 ports. + + See <http://lv2plug.in/ns/ext/port-groups> for details. + + @{ +*/ + +// clang-format off + +#define LV2_PORT_GROUPS_URI "http://lv2plug.in/ns/ext/port-groups" ///< http://lv2plug.in/ns/ext/port-groups +#define LV2_PORT_GROUPS_PREFIX LV2_PORT_GROUPS_URI "#" ///< http://lv2plug.in/ns/ext/port-groups# + +#define LV2_PORT_GROUPS__DiscreteGroup LV2_PORT_GROUPS_PREFIX "DiscreteGroup" ///< http://lv2plug.in/ns/ext/port-groups#DiscreteGroup +#define LV2_PORT_GROUPS__Element LV2_PORT_GROUPS_PREFIX "Element" ///< http://lv2plug.in/ns/ext/port-groups#Element +#define LV2_PORT_GROUPS__FivePointOneGroup LV2_PORT_GROUPS_PREFIX "FivePointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#FivePointOneGroup +#define LV2_PORT_GROUPS__FivePointZeroGroup LV2_PORT_GROUPS_PREFIX "FivePointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#FivePointZeroGroup +#define LV2_PORT_GROUPS__FourPointZeroGroup LV2_PORT_GROUPS_PREFIX "FourPointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#FourPointZeroGroup +#define LV2_PORT_GROUPS__Group LV2_PORT_GROUPS_PREFIX "Group" ///< http://lv2plug.in/ns/ext/port-groups#Group +#define LV2_PORT_GROUPS__InputGroup LV2_PORT_GROUPS_PREFIX "InputGroup" ///< http://lv2plug.in/ns/ext/port-groups#InputGroup +#define LV2_PORT_GROUPS__MidSideGroup LV2_PORT_GROUPS_PREFIX "MidSideGroup" ///< http://lv2plug.in/ns/ext/port-groups#MidSideGroup +#define LV2_PORT_GROUPS__MonoGroup LV2_PORT_GROUPS_PREFIX "MonoGroup" ///< http://lv2plug.in/ns/ext/port-groups#MonoGroup +#define LV2_PORT_GROUPS__OutputGroup LV2_PORT_GROUPS_PREFIX "OutputGroup" ///< http://lv2plug.in/ns/ext/port-groups#OutputGroup +#define LV2_PORT_GROUPS__SevenPointOneGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#SevenPointOneGroup +#define LV2_PORT_GROUPS__SevenPointOneWideGroup LV2_PORT_GROUPS_PREFIX "SevenPointOneWideGroup" ///< http://lv2plug.in/ns/ext/port-groups#SevenPointOneWideGroup +#define LV2_PORT_GROUPS__SixPointOneGroup LV2_PORT_GROUPS_PREFIX "SixPointOneGroup" ///< http://lv2plug.in/ns/ext/port-groups#SixPointOneGroup +#define LV2_PORT_GROUPS__StereoGroup LV2_PORT_GROUPS_PREFIX "StereoGroup" ///< http://lv2plug.in/ns/ext/port-groups#StereoGroup +#define LV2_PORT_GROUPS__ThreePointZeroGroup LV2_PORT_GROUPS_PREFIX "ThreePointZeroGroup" ///< http://lv2plug.in/ns/ext/port-groups#ThreePointZeroGroup +#define LV2_PORT_GROUPS__center LV2_PORT_GROUPS_PREFIX "center" ///< http://lv2plug.in/ns/ext/port-groups#center +#define LV2_PORT_GROUPS__centerLeft LV2_PORT_GROUPS_PREFIX "centerLeft" ///< http://lv2plug.in/ns/ext/port-groups#centerLeft +#define LV2_PORT_GROUPS__centerRight LV2_PORT_GROUPS_PREFIX "centerRight" ///< http://lv2plug.in/ns/ext/port-groups#centerRight +#define LV2_PORT_GROUPS__element LV2_PORT_GROUPS_PREFIX "element" ///< http://lv2plug.in/ns/ext/port-groups#element +#define LV2_PORT_GROUPS__group LV2_PORT_GROUPS_PREFIX "group" ///< http://lv2plug.in/ns/ext/port-groups#group +#define LV2_PORT_GROUPS__left LV2_PORT_GROUPS_PREFIX "left" ///< http://lv2plug.in/ns/ext/port-groups#left +#define LV2_PORT_GROUPS__lowFrequencyEffects LV2_PORT_GROUPS_PREFIX "lowFrequencyEffects" ///< http://lv2plug.in/ns/ext/port-groups#lowFrequencyEffects +#define LV2_PORT_GROUPS__mainInput LV2_PORT_GROUPS_PREFIX "mainInput" ///< http://lv2plug.in/ns/ext/port-groups#mainInput +#define LV2_PORT_GROUPS__mainOutput LV2_PORT_GROUPS_PREFIX "mainOutput" ///< http://lv2plug.in/ns/ext/port-groups#mainOutput +#define LV2_PORT_GROUPS__rearCenter LV2_PORT_GROUPS_PREFIX "rearCenter" ///< http://lv2plug.in/ns/ext/port-groups#rearCenter +#define LV2_PORT_GROUPS__rearLeft LV2_PORT_GROUPS_PREFIX "rearLeft" ///< http://lv2plug.in/ns/ext/port-groups#rearLeft +#define LV2_PORT_GROUPS__rearRight LV2_PORT_GROUPS_PREFIX "rearRight" ///< http://lv2plug.in/ns/ext/port-groups#rearRight +#define LV2_PORT_GROUPS__right LV2_PORT_GROUPS_PREFIX "right" ///< http://lv2plug.in/ns/ext/port-groups#right +#define LV2_PORT_GROUPS__side LV2_PORT_GROUPS_PREFIX "side" ///< http://lv2plug.in/ns/ext/port-groups#side +#define LV2_PORT_GROUPS__sideChainOf LV2_PORT_GROUPS_PREFIX "sideChainOf" ///< http://lv2plug.in/ns/ext/port-groups#sideChainOf +#define LV2_PORT_GROUPS__sideLeft LV2_PORT_GROUPS_PREFIX "sideLeft" ///< http://lv2plug.in/ns/ext/port-groups#sideLeft +#define LV2_PORT_GROUPS__sideRight LV2_PORT_GROUPS_PREFIX "sideRight" ///< http://lv2plug.in/ns/ext/port-groups#sideRight +#define LV2_PORT_GROUPS__source LV2_PORT_GROUPS_PREFIX "source" ///< http://lv2plug.in/ns/ext/port-groups#source +#define LV2_PORT_GROUPS__subGroupOf LV2_PORT_GROUPS_PREFIX "subGroupOf" ///< http://lv2plug.in/ns/ext/port-groups#subGroupOf + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_PORT_GROUPS_H */ diff --git a/include/lv2/port-props/port-props.h b/include/lv2/port-props/port-props.h new file mode 100644 index 0000000..ff4adcd --- /dev/null +++ b/include/lv2/port-props/port-props.h @@ -0,0 +1,53 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_PORT_PROPS_H +#define LV2_PORT_PROPS_H + +/** + @defgroup port-props Port Properties + @ingroup lv2 + + Various port properties. + + @{ +*/ + +// clang-format off + +#define LV2_PORT_PROPS_URI "http://lv2plug.in/ns/ext/port-props" ///< http://lv2plug.in/ns/ext/port-props +#define LV2_PORT_PROPS_PREFIX LV2_PORT_PROPS_URI "#" ///< http://lv2plug.in/ns/ext/port-props# + +#define LV2_PORT_PROPS__causesArtifacts LV2_PORT_PROPS_PREFIX "causesArtifacts" ///< http://lv2plug.in/ns/ext/port-props#causesArtifacts +#define LV2_PORT_PROPS__continuousCV LV2_PORT_PROPS_PREFIX "continuousCV" ///< http://lv2plug.in/ns/ext/port-props#continuousCV +#define LV2_PORT_PROPS__discreteCV LV2_PORT_PROPS_PREFIX "discreteCV" ///< http://lv2plug.in/ns/ext/port-props#discreteCV +#define LV2_PORT_PROPS__displayPriority LV2_PORT_PROPS_PREFIX "displayPriority" ///< http://lv2plug.in/ns/ext/port-props#displayPriority +#define LV2_PORT_PROPS__expensive LV2_PORT_PROPS_PREFIX "expensive" ///< http://lv2plug.in/ns/ext/port-props#expensive +#define LV2_PORT_PROPS__hasStrictBounds LV2_PORT_PROPS_PREFIX "hasStrictBounds" ///< http://lv2plug.in/ns/ext/port-props#hasStrictBounds +#define LV2_PORT_PROPS__logarithmic LV2_PORT_PROPS_PREFIX "logarithmic" ///< http://lv2plug.in/ns/ext/port-props#logarithmic +#define LV2_PORT_PROPS__notAutomatic LV2_PORT_PROPS_PREFIX "notAutomatic" ///< http://lv2plug.in/ns/ext/port-props#notAutomatic +#define LV2_PORT_PROPS__notOnGUI LV2_PORT_PROPS_PREFIX "notOnGUI" ///< http://lv2plug.in/ns/ext/port-props#notOnGUI +#define LV2_PORT_PROPS__rangeSteps LV2_PORT_PROPS_PREFIX "rangeSteps" ///< http://lv2plug.in/ns/ext/port-props#rangeSteps +#define LV2_PORT_PROPS__supportsStrictBounds LV2_PORT_PROPS_PREFIX "supportsStrictBounds" ///< http://lv2plug.in/ns/ext/port-props#supportsStrictBounds +#define LV2_PORT_PROPS__trigger LV2_PORT_PROPS_PREFIX "trigger" ///< http://lv2plug.in/ns/ext/port-props#trigger + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_PORT_PROPS_H */ diff --git a/include/lv2/presets/presets.h b/include/lv2/presets/presets.h new file mode 100644 index 0000000..716ab32 --- /dev/null +++ b/include/lv2/presets/presets.h @@ -0,0 +1,48 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_PRESETS_H +#define LV2_PRESETS_H + +/** + @defgroup presets Presets + @ingroup lv2 + + Presets for plugins. + + See <http://lv2plug.in/ns/ext/presets> for details. + + @{ +*/ + +// clang-format off + +#define LV2_PRESETS_URI "http://lv2plug.in/ns/ext/presets" ///< http://lv2plug.in/ns/ext/presets +#define LV2_PRESETS_PREFIX LV2_PRESETS_URI "#" ///< http://lv2plug.in/ns/ext/presets# + +#define LV2_PRESETS__Bank LV2_PRESETS_PREFIX "Bank" ///< http://lv2plug.in/ns/ext/presets#Bank +#define LV2_PRESETS__Preset LV2_PRESETS_PREFIX "Preset" ///< http://lv2plug.in/ns/ext/presets#Preset +#define LV2_PRESETS__bank LV2_PRESETS_PREFIX "bank" ///< http://lv2plug.in/ns/ext/presets#bank +#define LV2_PRESETS__preset LV2_PRESETS_PREFIX "preset" ///< http://lv2plug.in/ns/ext/presets#preset +#define LV2_PRESETS__value LV2_PRESETS_PREFIX "value" ///< http://lv2plug.in/ns/ext/presets#value + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_PRESETS_H */ diff --git a/include/lv2/resize-port/resize-port.h b/include/lv2/resize-port/resize-port.h new file mode 100644 index 0000000..a3a11c4 --- /dev/null +++ b/include/lv2/resize-port/resize-port.h @@ -0,0 +1,89 @@ +/* + Copyright 2007-2016 David Robillard <d@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. +*/ + +#ifndef LV2_RESIZE_PORT_H +#define LV2_RESIZE_PORT_H + +/** + @defgroup resize-port Resize Port + @ingroup lv2 + + Dynamically sized LV2 port buffers. + + @{ +*/ + +#include <stddef.h> +#include <stdint.h> + +// clang-format off + +#define LV2_RESIZE_PORT_URI "http://lv2plug.in/ns/ext/resize-port" ///< http://lv2plug.in/ns/ext/resize-port +#define LV2_RESIZE_PORT_PREFIX LV2_RESIZE_PORT_URI "#" ///< http://lv2plug.in/ns/ext/resize-port# + +#define LV2_RESIZE_PORT__asLargeAs LV2_RESIZE_PORT_PREFIX "asLargeAs" ///< http://lv2plug.in/ns/ext/resize-port#asLargeAs +#define LV2_RESIZE_PORT__minimumSize LV2_RESIZE_PORT_PREFIX "minimumSize" ///< http://lv2plug.in/ns/ext/resize-port#minimumSize +#define LV2_RESIZE_PORT__resize LV2_RESIZE_PORT_PREFIX "resize" ///< http://lv2plug.in/ns/ext/resize-port#resize + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +/** A status code for state functions. */ +typedef enum { + LV2_RESIZE_PORT_SUCCESS = 0, /**< Completed successfully. */ + LV2_RESIZE_PORT_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_RESIZE_PORT_ERR_NO_SPACE = 2 /**< Insufficient space. */ +} LV2_Resize_Port_Status; + +/** Opaque data for resize method. */ +typedef void* LV2_Resize_Port_Feature_Data; + +/** Host feature to allow plugins to resize their port buffers. */ +typedef struct { + /** Opaque data for resize method. */ + LV2_Resize_Port_Feature_Data data; + + /** + Resize a port buffer to at least `size` bytes. + + This function MAY return an error, in which case the port buffer was not + resized and the port is still connected to the same location. Plugins + MUST gracefully handle this situation. + + This function is in the audio threading class. + + The host MUST preserve the contents of the port buffer when resizing. + + Plugins MAY resize a port many times in a single run callback. Hosts + SHOULD make this as inexpensive as possible. + */ + LV2_Resize_Port_Status (*resize)(LV2_Resize_Port_Feature_Data data, + uint32_t index, + size_t size); +} LV2_Resize_Port_Resize; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_RESIZE_PORT_H */ diff --git a/include/lv2/state/state.h b/include/lv2/state/state.h new file mode 100644 index 0000000..01ec598 --- /dev/null +++ b/include/lv2/state/state.h @@ -0,0 +1,392 @@ +/* + Copyright 2010-2016 David Robillard <d@drobilla.net> + Copyright 2010 Leonard Ritter <paniq@paniq.org> + + 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. +*/ + +#ifndef LV2_STATE_H +#define LV2_STATE_H + +/** + @defgroup state State + @ingroup lv2 + + An interface for LV2 plugins to save and restore state. + + See <http://lv2plug.in/ns/ext/state> for details. + + @{ +*/ + +#include "lv2/core/lv2.h" + +#include <stddef.h> +#include <stdint.h> + +// clang-format off + +#define LV2_STATE_URI "http://lv2plug.in/ns/ext/state" ///< http://lv2plug.in/ns/ext/state +#define LV2_STATE_PREFIX LV2_STATE_URI "#" ///< http://lv2plug.in/ns/ext/state# + +#define LV2_STATE__State LV2_STATE_PREFIX "State" ///< http://lv2plug.in/ns/ext/state#State +#define LV2_STATE__interface LV2_STATE_PREFIX "interface" ///< http://lv2plug.in/ns/ext/state#interface +#define LV2_STATE__loadDefaultState LV2_STATE_PREFIX "loadDefaultState" ///< http://lv2plug.in/ns/ext/state#loadDefaultState +#define LV2_STATE__freePath LV2_STATE_PREFIX "freePath" ///< http://lv2plug.in/ns/ext/state#freePath +#define LV2_STATE__makePath LV2_STATE_PREFIX "makePath" ///< http://lv2plug.in/ns/ext/state#makePath +#define LV2_STATE__mapPath LV2_STATE_PREFIX "mapPath" ///< http://lv2plug.in/ns/ext/state#mapPath +#define LV2_STATE__state LV2_STATE_PREFIX "state" ///< http://lv2plug.in/ns/ext/state#state +#define LV2_STATE__threadSafeRestore LV2_STATE_PREFIX "threadSafeRestore" ///< http://lv2plug.in/ns/ext/state#threadSafeRestore +#define LV2_STATE__StateChanged LV2_STATE_PREFIX "StateChanged" ///< http://lv2plug.in/ns/ext/state#StateChanged + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* LV2_State_Handle; ///< Opaque handle for state save/restore +typedef void* + LV2_State_Free_Path_Handle; ///< Opaque handle for state:freePath feature +typedef void* + LV2_State_Map_Path_Handle; ///< Opaque handle for state:mapPath feature +typedef void* + LV2_State_Make_Path_Handle; ///< Opaque handle for state:makePath feature + +/** + Flags describing value characteristics. + + These flags are used along with the value's type URI to determine how to + (de-)serialise the value data, or whether it is even possible to do so. +*/ +typedef enum { + /** + Plain Old Data. + + Values with this flag contain no pointers or references to other areas + of memory. It is safe to copy POD values with a simple memcpy and store + them for the duration of the process. A POD value is not necessarily + safe to transmit between processes or machines (for example, filenames + are POD), see LV2_STATE_IS_PORTABLE for details. + + Implementations MUST NOT attempt to copy or serialise a non-POD value if + they do not understand its type (and thus know how to correctly do so). + */ + LV2_STATE_IS_POD = 1u << 0u, + + /** + Portable (architecture independent) data. + + Values with this flag are in a format that is usable on any + architecture. A portable value saved on one machine can be restored on + another machine regardless of architecture. The format of portable + values MUST NOT depend on architecture-specific properties like + endianness or alignment. Portable values MUST NOT contain filenames. + */ + LV2_STATE_IS_PORTABLE = 1u << 1u, + + /** + Native data. + + This flag is used by the host to indicate that the saved data is only + going to be used locally in the currently running process (for things + like instance duplication or snapshots), so the plugin should use the + most efficient representation possible and not worry about serialisation + and portability. + */ + LV2_STATE_IS_NATIVE = 1u << 2u +} LV2_State_Flags; + +/** A status code for state functions. */ +typedef enum { + LV2_STATE_SUCCESS = 0, /**< Completed successfully. */ + LV2_STATE_ERR_UNKNOWN = 1, /**< Unknown error. */ + LV2_STATE_ERR_BAD_TYPE = 2, /**< Failed due to unsupported type. */ + LV2_STATE_ERR_BAD_FLAGS = 3, /**< Failed due to unsupported flags. */ + LV2_STATE_ERR_NO_FEATURE = 4, /**< Failed due to missing features. */ + LV2_STATE_ERR_NO_PROPERTY = 5, /**< Failed due to missing property. */ + LV2_STATE_ERR_NO_SPACE = 6 /**< Failed due to insufficient space. */ +} LV2_State_Status; + +/** + A host-provided function to store a property. + @param handle Must be the handle passed to LV2_State_Interface.save(). + @param key The key to store `value` under (URID). + @param value Pointer to the value to be stored. + @param size The size of `value` in bytes. + @param type The type of `value` (URID). + @param flags LV2_State_Flags for `value`. + @return 0 on success, otherwise a non-zero error code. + + The host passes a callback of this type to LV2_State_Interface.save(). This + callback is called repeatedly by the plugin to store all the properties that + describe its current state. + + DO NOT INVENT NONSENSE URI SCHEMES FOR THE KEY. Best is to use keys from + existing vocabularies. If nothing appropriate is available, use http URIs + that point to somewhere you can host documents so documentation can be made + resolvable (typically a child of the plugin or project URI). If this is not + possible, invent a URN scheme, e.g. urn:myproj:whatever. The plugin MUST + NOT pass an invalid URI key. + + The host MAY fail to store a property for whatever reason, but SHOULD + store any property that is LV2_STATE_IS_POD and LV2_STATE_IS_PORTABLE. + Implementations SHOULD use the types from the LV2 Atom extension + (http://lv2plug.in/ns/ext/atom) wherever possible. The plugin SHOULD + attempt to fall-back and avoid the error if possible. + + Note that `size` MUST be > 0, and `value` MUST point to a valid region of + memory `size` bytes long (this is required to make restore unambiguous). + + The plugin MUST NOT attempt to use this function outside of the + LV2_State_Interface.restore() context. +*/ +typedef LV2_State_Status (*LV2_State_Store_Function)(LV2_State_Handle handle, + uint32_t key, + const void* value, + size_t size, + uint32_t type, + uint32_t flags); + +/** + A host-provided function to retrieve a property. + @param handle Must be the handle passed to LV2_State_Interface.restore(). + @param key The key of the property to retrieve (URID). + @param size (Output) If non-NULL, set to the size of the restored value. + @param type (Output) If non-NULL, set to the type of the restored value. + @param flags (Output) If non-NULL, set to the flags for the restored value. + @return A pointer to the restored value (object), or NULL if no value + has been stored under `key`. + + A callback of this type is passed by the host to + LV2_State_Interface.restore(). This callback is called repeatedly by the + plugin to retrieve any properties it requires to restore its state. + + The returned value MUST remain valid until LV2_State_Interface.restore() + returns. The plugin MUST NOT attempt to use this function, or any value + returned from it, outside of the LV2_State_Interface.restore() context. +*/ +typedef const void* (*LV2_State_Retrieve_Function)(LV2_State_Handle handle, + uint32_t key, + size_t* size, + uint32_t* type, + uint32_t* flags); + +/** + LV2 Plugin State Interface. + + When the plugin's extension_data is called with argument + LV2_STATE__interface, the plugin MUST return an LV2_State_Interface + structure, which remains valid for the lifetime of the plugin. + + The host can use the contained function pointers to save and restore the + state of a plugin instance at any time, provided the threading restrictions + of the functions are met. + + Stored data is only guaranteed to be compatible between instances of plugins + with the same URI (i.e. if a change to a plugin would cause a fatal error + when restoring state saved by a previous version of that plugin, the plugin + URI MUST change just as it must when ports change incompatibly). Plugin + authors should consider this possibility, and always store sensible data + with meaningful types to avoid such problems in the future. +*/ +typedef struct { + /** + Save plugin state using a host-provided `store` callback. + + @param instance The instance handle of the plugin. + @param store The host-provided store callback. + @param handle An opaque pointer to host data which MUST be passed as the + handle parameter to `store` if it is called. + @param flags Flags describing desired properties of this save. These + flags may be used to determine the most appropriate values to store. + @param features Extensible parameter for passing any additional + features to be used for this save. + + The plugin is expected to store everything necessary to completely + restore its state later. Plugins SHOULD store simple POD data whenever + possible, and consider the possibility of state being restored much + later on a different machine. + + The `handle` pointer and `store` function MUST NOT be used + beyond the scope of save(). + + This function has its own special threading class: it may not be called + concurrently with any "Instantiation" function, but it may be called + concurrently with functions in any other class, unless the definition of + that class prohibits it (for example, it may not be called concurrently + with a "Discovery" function, but it may be called concurrently with an + "Audio" function. The plugin is responsible for any locking or + lock-free techniques necessary to make this possible. + + Note that in the simple case where state is only modified by restore(), + there are no synchronization issues since save() is never called + concurrently with restore() (though run() may read it during a save). + + Plugins that dynamically modify state while running, however, must take + care to do so in such a way that a concurrent call to save() will save a + consistent representation of plugin state for a single instant in time. + */ + LV2_State_Status (*save)(LV2_Handle instance, + LV2_State_Store_Function store, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature* const* features); + + /** + Restore plugin state using a host-provided `retrieve` callback. + + @param instance The instance handle of the plugin. + @param retrieve The host-provided retrieve callback. + @param handle An opaque pointer to host data which MUST be passed as the + handle parameter to `retrieve` if it is called. + @param flags Currently unused. + @param features Extensible parameter for passing any additional + features to be used for this restore. + + The plugin MAY assume a restored value was set by a previous call to + LV2_State_Interface.save() by a plugin with the same URI. + + The plugin MUST gracefully fall back to a default value when a value can + not be retrieved. This allows the host to reset the plugin state with + an empty map. + + The `handle` pointer and `store` function MUST NOT be used + beyond the scope of restore(). + + This function is in the "Instantiation" threading class as defined by + LV2. This means it MUST NOT be called concurrently with any other + function on the same plugin instance. + */ + LV2_State_Status (*restore)(LV2_Handle instance, + LV2_State_Retrieve_Function retrieve, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature* const* features); +} LV2_State_Interface; + +/** + Feature data for state:mapPath (@ref LV2_STATE__mapPath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Map_Path_Handle handle; + + /** + Map an absolute path to an abstract path for use in plugin state. + @param handle MUST be the `handle` member of this struct. + @param absolute_path The absolute path of a file. + @return An abstract path suitable for use in plugin state. + + The plugin MUST use this function to map any paths that will be stored + in plugin state. The returned value is an abstract path which MAY not + be an actual file system path; absolute_path() MUST be used to map + it to an actual path in order to use the file. + + Plugins MUST NOT make any assumptions about abstract paths except that + they can be mapped back to the absolute path of the "same" file (though + not necessarily the same original path) using absolute_path(). + + This function may only be called within the context of + LV2_State_Interface methods. The caller must free the returned value + with LV2_State_Free_Path.free_path(). + */ + char* (*abstract_path)(LV2_State_Map_Path_Handle handle, + const char* absolute_path); + + /** + Map an abstract path from plugin state to an absolute path. + @param handle MUST be the `handle` member of this struct. + @param abstract_path An abstract path (typically from plugin state). + @return An absolute file system path. + + The plugin MUST use this function in order to actually open or otherwise + use any paths loaded from plugin state. + + This function may only be called within the context of + LV2_State_Interface methods. The caller must free the returned value + with LV2_State_Free_Path.free_path(). + */ + char* (*absolute_path)(LV2_State_Map_Path_Handle handle, + const char* abstract_path); +} LV2_State_Map_Path; + +/** + Feature data for state:makePath (@ref LV2_STATE__makePath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Make_Path_Handle handle; + + /** + Return a path the plugin may use to create a new file. + @param handle MUST be the `handle` member of this struct. + @param path The path of the new file within a namespace unique to this + plugin instance. + @return The absolute path to use for the new file. + + This function can be used by plugins to create files and directories, + either at state saving time (if this feature is passed to + LV2_State_Interface.save()) or any time (if this feature is passed to + LV2_Descriptor.instantiate()). + + The host MUST do whatever is necessary for the plugin to be able to + create a file at the returned path (for example, using fopen()), + including creating any leading directories. + + If this function is passed to LV2_Descriptor.instantiate(), it may be + called from any non-realtime context. If it is passed to + LV2_State_Interface.save(), it may only be called within the dynamic + scope of that function call. + + The caller must free the returned value with + LV2_State_Free_Path.free_path(). + */ + char* (*path)(LV2_State_Make_Path_Handle handle, const char* path); +} LV2_State_Make_Path; + +/** + Feature data for state:freePath (@ref LV2_STATE__freePath). +*/ +typedef struct { + /** + Opaque host data. + */ + LV2_State_Free_Path_Handle handle; + + /** + Free a path returned by a state feature. + + @param handle MUST be the `handle` member of this struct. + @param path The path previously returned by a state feature. + + This function can be used by plugins to free paths allocated by the host + and returned by state features (LV2_State_Map_Path.abstract_path(), + LV2_State_Map_Path.absolute_path(), and LV2_State_Make_Path.path()). + */ + void (*free_path)(LV2_State_Free_Path_Handle handle, char* path); +} LV2_State_Free_Path; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_STATE_H */ diff --git a/include/lv2/time/time.h b/include/lv2/time/time.h new file mode 100644 index 0000000..1dce219 --- /dev/null +++ b/include/lv2/time/time.h @@ -0,0 +1,59 @@ +/* + Copyright 2011-2016 David Robillard <d@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. +*/ + +#ifndef LV2_TIME_H +#define LV2_TIME_H + +/** + @defgroup time Time + @ingroup lv2 + + Properties for describing time. + + Note the time extension is purely data, this header merely defines URIs for + convenience. + + See <http://lv2plug.in/ns/ext/time> for details. + + @{ +*/ + +// clang-format off + +#define LV2_TIME_URI "http://lv2plug.in/ns/ext/time" ///< http://lv2plug.in/ns/ext/time +#define LV2_TIME_PREFIX LV2_TIME_URI "#" ///< http://lv2plug.in/ns/ext/time# + +#define LV2_TIME__Time LV2_TIME_PREFIX "Time" ///< http://lv2plug.in/ns/ext/time#Time +#define LV2_TIME__Position LV2_TIME_PREFIX "Position" ///< http://lv2plug.in/ns/ext/time#Position +#define LV2_TIME__Rate LV2_TIME_PREFIX "Rate" ///< http://lv2plug.in/ns/ext/time#Rate +#define LV2_TIME__position LV2_TIME_PREFIX "position" ///< http://lv2plug.in/ns/ext/time#position +#define LV2_TIME__barBeat LV2_TIME_PREFIX "barBeat" ///< http://lv2plug.in/ns/ext/time#barBeat +#define LV2_TIME__bar LV2_TIME_PREFIX "bar" ///< http://lv2plug.in/ns/ext/time#bar +#define LV2_TIME__beat LV2_TIME_PREFIX "beat" ///< http://lv2plug.in/ns/ext/time#beat +#define LV2_TIME__beatUnit LV2_TIME_PREFIX "beatUnit" ///< http://lv2plug.in/ns/ext/time#beatUnit +#define LV2_TIME__beatsPerBar LV2_TIME_PREFIX "beatsPerBar" ///< http://lv2plug.in/ns/ext/time#beatsPerBar +#define LV2_TIME__beatsPerMinute LV2_TIME_PREFIX "beatsPerMinute" ///< http://lv2plug.in/ns/ext/time#beatsPerMinute +#define LV2_TIME__frame LV2_TIME_PREFIX "frame" ///< http://lv2plug.in/ns/ext/time#frame +#define LV2_TIME__framesPerSecond LV2_TIME_PREFIX "framesPerSecond" ///< http://lv2plug.in/ns/ext/time#framesPerSecond +#define LV2_TIME__speed LV2_TIME_PREFIX "speed" ///< http://lv2plug.in/ns/ext/time#speed + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_TIME_H */ diff --git a/include/lv2/ui/ui.h b/include/lv2/ui/ui.h new file mode 100644 index 0000000..fb41d90 --- /dev/null +++ b/include/lv2/ui/ui.h @@ -0,0 +1,543 @@ +/* + LV2 UI Extension + Copyright 2009-2016 David Robillard <d@drobilla.net> + Copyright 2006-2011 Lars Luthman <lars.luthman@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. +*/ + +#ifndef LV2_UI_H +#define LV2_UI_H + +/** + @defgroup ui User Interfaces + @ingroup lv2 + + User interfaces of any type for plugins. + + See <http://lv2plug.in/ns/extensions/ui> for details. + + @{ +*/ + +#include "lv2/core/lv2.h" +#include "lv2/urid/urid.h" + +#include <stdbool.h> +#include <stdint.h> + +// clang-format off + +#define LV2_UI_URI "http://lv2plug.in/ns/extensions/ui" ///< http://lv2plug.in/ns/extensions/ui +#define LV2_UI_PREFIX LV2_UI_URI "#" ///< http://lv2plug.in/ns/extensions/ui# + +#define LV2_UI__CocoaUI LV2_UI_PREFIX "CocoaUI" ///< http://lv2plug.in/ns/extensions/ui#CocoaUI +#define LV2_UI__Gtk3UI LV2_UI_PREFIX "Gtk3UI" ///< http://lv2plug.in/ns/extensions/ui#Gtk3UI +#define LV2_UI__GtkUI LV2_UI_PREFIX "GtkUI" ///< http://lv2plug.in/ns/extensions/ui#GtkUI +#define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification" ///< http://lv2plug.in/ns/extensions/ui#PortNotification +#define LV2_UI__PortProtocol LV2_UI_PREFIX "PortProtocol" ///< http://lv2plug.in/ns/extensions/ui#PortProtocol +#define LV2_UI__Qt4UI LV2_UI_PREFIX "Qt4UI" ///< http://lv2plug.in/ns/extensions/ui#Qt4UI +#define LV2_UI__Qt5UI LV2_UI_PREFIX "Qt5UI" ///< http://lv2plug.in/ns/extensions/ui#Qt5UI +#define LV2_UI__UI LV2_UI_PREFIX "UI" ///< http://lv2plug.in/ns/extensions/ui#UI +#define LV2_UI__WindowsUI LV2_UI_PREFIX "WindowsUI" ///< http://lv2plug.in/ns/extensions/ui#WindowsUI +#define LV2_UI__X11UI LV2_UI_PREFIX "X11UI" ///< http://lv2plug.in/ns/extensions/ui#X11UI +#define LV2_UI__binary LV2_UI_PREFIX "binary" ///< http://lv2plug.in/ns/extensions/ui#binary +#define LV2_UI__fixedSize LV2_UI_PREFIX "fixedSize" ///< http://lv2plug.in/ns/extensions/ui#fixedSize +#define LV2_UI__idleInterface LV2_UI_PREFIX "idleInterface" ///< http://lv2plug.in/ns/extensions/ui#idleInterface +#define LV2_UI__noUserResize LV2_UI_PREFIX "noUserResize" ///< http://lv2plug.in/ns/extensions/ui#noUserResize +#define LV2_UI__notifyType LV2_UI_PREFIX "notifyType" ///< http://lv2plug.in/ns/extensions/ui#notifyType +#define LV2_UI__parent LV2_UI_PREFIX "parent" ///< http://lv2plug.in/ns/extensions/ui#parent +#define LV2_UI__plugin LV2_UI_PREFIX "plugin" ///< http://lv2plug.in/ns/extensions/ui#plugin +#define LV2_UI__portIndex LV2_UI_PREFIX "portIndex" ///< http://lv2plug.in/ns/extensions/ui#portIndex +#define LV2_UI__portMap LV2_UI_PREFIX "portMap" ///< http://lv2plug.in/ns/extensions/ui#portMap +#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification" ///< http://lv2plug.in/ns/extensions/ui#portNotification +#define LV2_UI__portSubscribe LV2_UI_PREFIX "portSubscribe" ///< http://lv2plug.in/ns/extensions/ui#portSubscribe +#define LV2_UI__protocol LV2_UI_PREFIX "protocol" ///< http://lv2plug.in/ns/extensions/ui#protocol +#define LV2_UI__requestValue LV2_UI_PREFIX "requestValue" ///< http://lv2plug.in/ns/extensions/ui#requestValue +#define LV2_UI__floatProtocol LV2_UI_PREFIX "floatProtocol" ///< http://lv2plug.in/ns/extensions/ui#floatProtocol +#define LV2_UI__peakProtocol LV2_UI_PREFIX "peakProtocol" ///< http://lv2plug.in/ns/extensions/ui#peakProtocol +#define LV2_UI__resize LV2_UI_PREFIX "resize" ///< http://lv2plug.in/ns/extensions/ui#resize +#define LV2_UI__showInterface LV2_UI_PREFIX "showInterface" ///< http://lv2plug.in/ns/extensions/ui#showInterface +#define LV2_UI__touch LV2_UI_PREFIX "touch" ///< http://lv2plug.in/ns/extensions/ui#touch +#define LV2_UI__ui LV2_UI_PREFIX "ui" ///< http://lv2plug.in/ns/extensions/ui#ui +#define LV2_UI__updateRate LV2_UI_PREFIX "updateRate" ///< http://lv2plug.in/ns/extensions/ui#updateRate +#define LV2_UI__windowTitle LV2_UI_PREFIX "windowTitle" ///< http://lv2plug.in/ns/extensions/ui#windowTitle +#define LV2_UI__scaleFactor LV2_UI_PREFIX "scaleFactor" ///< http://lv2plug.in/ns/extensions/ui#scaleFactor +#define LV2_UI__foregroundColor LV2_UI_PREFIX "foregroundColor" ///< http://lv2plug.in/ns/extensions/ui#foregroundColor +#define LV2_UI__backgroundColor LV2_UI_PREFIX "backgroundColor" ///< http://lv2plug.in/ns/extensions/ui#backgroundColor + +// clang-format on + +/** + The index returned by LV2UI_Port_Map::port_index() for unknown ports. +*/ +#define LV2UI_INVALID_PORT_INDEX ((uint32_t)-1) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + A pointer to some widget or other type of UI handle. + + The actual type is defined by the type of the UI. +*/ +typedef void* LV2UI_Widget; + +/** + A pointer to UI instance internals. + + The host may compare this to NULL, but otherwise MUST NOT interpret it. +*/ +typedef void* LV2UI_Handle; + +/** + A pointer to a controller provided by the host. + + The UI may compare this to NULL, but otherwise MUST NOT interpret it. +*/ +typedef void* LV2UI_Controller; + +/** + A pointer to opaque data for a feature. +*/ +typedef void* LV2UI_Feature_Handle; + +/** + A host-provided function that sends data to a plugin's input ports. + + @param controller The opaque controller pointer passed to + LV2UI_Descriptor::instantiate(). + + @param port_index Index of the port to update. + + @param buffer Buffer containing `buffer_size` bytes of data. + + @param buffer_size Size of `buffer` in bytes. + + @param port_protocol Either 0 or the URID for a ui:PortProtocol. If 0, the + protocol is implicitly ui:floatProtocol, the port MUST be an lv2:ControlPort + input, `buffer` MUST point to a single float value, and `buffer_size` MUST + be sizeof(float). The UI SHOULD NOT use a protocol not supported by the + host, but the host MUST gracefully ignore any protocol it does not + understand. +*/ +typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller, + uint32_t port_index, + uint32_t buffer_size, + uint32_t port_protocol, + const void* buffer); + +/** + A plugin UI. + + A pointer to an object of this type is returned by the lv2ui_descriptor() + function. +*/ +typedef struct LV2UI_Descriptor { + /** + The URI for this UI (not for the plugin it controls). + */ + const char* URI; + + /** + Create a new UI and return a handle to it. This function works + similarly to LV2_Descriptor::instantiate(). + + @param descriptor The descriptor for the UI to instantiate. + + @param plugin_uri The URI of the plugin that this UI will control. + + @param bundle_path The path to the bundle containing this UI, including + the trailing directory separator. + + @param write_function A function that the UI can use to send data to the + plugin's input ports. + + @param controller A handle for the UI instance to be passed as the + first parameter of UI methods. + + @param widget (output) widget pointer. The UI points this at its main + widget, which has the type defined by the UI type in the data file. + + @param features An array of LV2_Feature pointers. The host must pass + all feature URIs that it and the UI supports and any additional data, as + in LV2_Descriptor::instantiate(). Note that UI features and plugin + features are not necessarily the same. + + */ + LV2UI_Handle (*instantiate)(const struct LV2UI_Descriptor* descriptor, + const char* plugin_uri, + const char* bundle_path, + LV2UI_Write_Function write_function, + LV2UI_Controller controller, + LV2UI_Widget* widget, + const LV2_Feature* const* features); + + /** + Destroy the UI. The host must not try to access the widget after + calling this function. + */ + void (*cleanup)(LV2UI_Handle ui); + + /** + Tell the UI that something interesting has happened at a plugin port. + + What is "interesting" and how it is written to `buffer` is defined by + `format`, which has the same meaning as in LV2UI_Write_Function(). + Format 0 is a special case for lv2:ControlPort, where this function + should be called when the port value changes (but not necessarily for + every change), `buffer_size` must be sizeof(float), and `buffer` + points to a single IEEE-754 float. + + By default, the host should only call this function for lv2:ControlPort + inputs. However, the UI can request updates for other ports statically + with ui:portNotification or dynamically with ui:portSubscribe. + + The UI MUST NOT retain any reference to `buffer` after this function + returns, it is only valid for the duration of the call. + + This member may be NULL if the UI is not interested in any port events. + */ + void (*port_event)(LV2UI_Handle ui, + uint32_t port_index, + uint32_t buffer_size, + uint32_t format, + const void* buffer); + + /** + Return a data structure associated with an extension URI, typically an + interface struct with additional function pointers + + This member may be set to NULL if the UI is not interested in supporting + any extensions. This is similar to LV2_Descriptor::extension_data(). + + */ + const void* (*extension_data)(const char* uri); +} LV2UI_Descriptor; + +/** + Feature/interface for resizable UIs (LV2_UI__resize). + + This structure is used in two ways: as a feature passed by the host via + LV2UI_Descriptor::instantiate(), or as an interface provided by a UI via + LV2UI_Descriptor::extension_data()). +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to ui_resize(). + */ + LV2UI_Feature_Handle handle; + + /** + Request/advertise a size change. + + When provided by the host, the UI may call this function to inform the + host about the size of the UI. + + When provided by the UI, the host may call this function to notify the + UI that it should change its size accordingly. In this case, the host + must pass the LV2UI_Handle to provide access to the UI instance. + + @return 0 on success. + */ + int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height); +} LV2UI_Resize; + +/** + Feature to map port symbols to UIs. + + This can be used by the UI to get the index for a port with the given + symbol. This makes it possible to implement and distribute a UI separately + from the plugin (since symbol, unlike index, is a stable port identifier). +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to port_index(). + */ + LV2UI_Feature_Handle handle; + + /** + Get the index for the port with the given `symbol`. + + @return The index of the port, or LV2UI_INVALID_PORT_INDEX if no such + port is found. + */ + uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); +} LV2UI_Port_Map; + +/** + Feature to subscribe to port updates (LV2_UI__portSubscribe). +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to subscribe() and + unsubscribe(). + */ + LV2UI_Feature_Handle handle; + + /** + Subscribe to updates for a port. + + This means that the host will call the UI's port_event() function when + the port value changes (as defined by protocol). + + Calling this function with the same `port_index` and `port_protocol` + as an already active subscription has no effect. + + @param handle The handle field of this struct. + @param port_index The index of the port. + @param port_protocol The URID of the ui:PortProtocol. + @param features Features for this subscription. + @return 0 on success. + */ + uint32_t (*subscribe)(LV2UI_Feature_Handle handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); + + /** + Unsubscribe from updates for a port. + + This means that the host will cease calling calling port_event() when + the port value changes. + + Calling this function with a `port_index` and `port_protocol` that + does not refer to an active port subscription has no effect. + + @param handle The handle field of this struct. + @param port_index The index of the port. + @param port_protocol The URID of the ui:PortProtocol. + @param features Features for this subscription. + @return 0 on success. + */ + uint32_t (*unsubscribe)(LV2UI_Feature_Handle handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); +} LV2UI_Port_Subscribe; + +/** + A feature to notify the host that the user has grabbed a UI control. +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to touch(). + */ + LV2UI_Feature_Handle handle; + + /** + Notify the host that a control has been grabbed or released. + + The host should cease automating the port or otherwise manipulating the + port value until the control has been ungrabbed. + + @param handle The handle field of this struct. + @param port_index The index of the port associated with the control. + @param grabbed If true, the control has been grabbed, otherwise the + control has been released. + */ + void (*touch)(LV2UI_Feature_Handle handle, uint32_t port_index, bool grabbed); +} LV2UI_Touch; + +/** + A status code for LV2UI_Request_Value::request(). +*/ +typedef enum { + /** + Completed successfully. + + The host will set the parameter later if the user chooses a new value. + */ + LV2UI_REQUEST_VALUE_SUCCESS, + + /** + Parameter already being requested. + + The host is already requesting a parameter from the user (for example, a + dialog is visible), or the UI is otherwise busy and can not make this + request. + */ + LV2UI_REQUEST_VALUE_BUSY, + + /** + Unknown parameter. + + The host is not aware of this parameter, and is not able to set a new + value for it. + */ + LV2UI_REQUEST_VALUE_ERR_UNKNOWN, + + /** + Unsupported parameter. + + The host knows about this parameter, but does not support requesting a + new value for it from the user. This is likely because the host does + not have UI support for choosing a value with the appropriate type. + */ + LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED +} LV2UI_Request_Value_Status; + +/** + A feature to request a new parameter value from the host. +*/ +typedef struct { + /** + Pointer to opaque data which must be passed to request(). + */ + LV2UI_Feature_Handle handle; + + /** + Request a value for a parameter from the host. + + This is mainly used by UIs to request values for complex parameters that + don't change often, such as file paths, but it may be used to request + any parameter value. + + This function returns immediately, and the return value indicates + whether the host can fulfil the request. The host may notify the + plugin about the new parameter value, for example when a file is + selected by the user, via the usual mechanism. Typically, the host will + send a message to the plugin that sets the new parameter value, and the + plugin will notify the UI via a message as usual for any other parameter + change. + + To provide an appropriate UI, the host can determine details about the + parameter from the plugin data as usual. The additional parameters of + this function provide support for more advanced use cases, but in the + simple common case, the plugin will simply pass the key of the desired + parameter and zero for everything else. + + @param handle The handle field of this struct. + + @param key The URID of the parameter. + + @param type The optional type of the value to request. This can be used + to request a specific value type for parameters that support several. + If non-zero, it must be the URID of an instance of rdfs:Class or + rdfs:Datatype. + + @param features Additional features for this request, or NULL. + + @return A status code which is 0 on success. + */ + LV2UI_Request_Value_Status (*request)(LV2UI_Feature_Handle handle, + LV2_URID key, + LV2_URID type, + const LV2_Feature* const* features); + +} LV2UI_Request_Value; + +/** + UI Idle Interface (LV2_UI__idleInterface) + + UIs can provide this interface to have an idle() callback called by the host + rapidly to update the UI. +*/ +typedef struct { + /** + Run a single iteration of the UI's idle loop. + + This will be called rapidly in the UI thread at a rate appropriate + for a toolkit main loop. There are no precise timing guarantees, but + the host should attempt to call idle() at a high enough rate for smooth + animation, at least 30Hz. + + @return non-zero if the UI has been closed, in which case the host + should stop calling idle(), and can either completely destroy the UI, or + re-show it and resume calling idle(). + */ + int (*idle)(LV2UI_Handle ui); +} LV2UI_Idle_Interface; + +/** + UI Show Interface (LV2_UI__showInterface) + + UIs can provide this interface to show and hide a window, which allows them + to function in hosts unable to embed their widget. This allows any UI to + provide a fallback for embedding that works in any host. + + If used: + - The host MUST use LV2UI_Idle_Interface to drive the UI. + - The UI MUST return non-zero from LV2UI_Idle_Interface::idle() when it has + been closed. + - If idle() returns non-zero, the host MUST call hide() and stop calling + idle(). It MAY later call show() then resume calling idle(). +*/ +typedef struct { + /** + Show a window for this UI. + + The window title MAY have been passed by the host to + LV2UI_Descriptor::instantiate() as an LV2_Options_Option with key + LV2_UI__windowTitle. + + @return 0 on success, or anything else to stop being called. + */ + int (*show)(LV2UI_Handle ui); + + /** + Hide the window for this UI. + + @return 0 on success, or anything else to stop being called. + */ + int (*hide)(LV2UI_Handle ui); +} LV2UI_Show_Interface; + +/** + Peak data for a slice of time, the update format for ui:peakProtocol. +*/ +typedef struct { + /** + The start of the measurement period. This is just a running counter + that is only meaningful in comparison to previous values and must not be + interpreted as an absolute time. + */ + uint32_t period_start; + + /** + The size of the measurement period, in the same units as period_start. + */ + uint32_t period_size; + + /** + The peak value for the measurement period. This should be the maximal + value for abs(sample) over all the samples in the period. + */ + float peak; +} LV2UI_Peak_Data; + +/** + Prototype for UI accessor function. + + This is the entry point to a UI library, which works in the same way as + lv2_descriptor() but for UIs rather than plugins. +*/ +LV2_SYMBOL_EXPORT +const LV2UI_Descriptor* +lv2ui_descriptor(uint32_t index); + +/** + The type of the lv2ui_descriptor() function. +*/ +typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index); + +#ifdef __cplusplus +} +#endif + +/** + @} +*/ + +#endif /* LV2_UI_H */ diff --git a/include/lv2/units/units.h b/include/lv2/units/units.h new file mode 100644 index 0000000..09ae16b --- /dev/null +++ b/include/lv2/units/units.h @@ -0,0 +1,75 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_UNITS_H +#define LV2_UNITS_H + +/** + @defgroup units Units + @ingroup lv2 + + Units for LV2 values. + + See <http://lv2plug.in/ns/extensions/units> for details. + + @{ +*/ + +// clang-format off + +#define LV2_UNITS_URI "http://lv2plug.in/ns/extensions/units" ///< http://lv2plug.in/ns/extensions/units +#define LV2_UNITS_PREFIX LV2_UNITS_URI "#" ///< http://lv2plug.in/ns/extensions/units# + +#define LV2_UNITS__Conversion LV2_UNITS_PREFIX "Conversion" ///< http://lv2plug.in/ns/extensions/units#Conversion +#define LV2_UNITS__Unit LV2_UNITS_PREFIX "Unit" ///< http://lv2plug.in/ns/extensions/units#Unit +#define LV2_UNITS__bar LV2_UNITS_PREFIX "bar" ///< http://lv2plug.in/ns/extensions/units#bar +#define LV2_UNITS__beat LV2_UNITS_PREFIX "beat" ///< http://lv2plug.in/ns/extensions/units#beat +#define LV2_UNITS__bpm LV2_UNITS_PREFIX "bpm" ///< http://lv2plug.in/ns/extensions/units#bpm +#define LV2_UNITS__cent LV2_UNITS_PREFIX "cent" ///< http://lv2plug.in/ns/extensions/units#cent +#define LV2_UNITS__cm LV2_UNITS_PREFIX "cm" ///< http://lv2plug.in/ns/extensions/units#cm +#define LV2_UNITS__coef LV2_UNITS_PREFIX "coef" ///< http://lv2plug.in/ns/extensions/units#coef +#define LV2_UNITS__conversion LV2_UNITS_PREFIX "conversion" ///< http://lv2plug.in/ns/extensions/units#conversion +#define LV2_UNITS__db LV2_UNITS_PREFIX "db" ///< http://lv2plug.in/ns/extensions/units#db +#define LV2_UNITS__degree LV2_UNITS_PREFIX "degree" ///< http://lv2plug.in/ns/extensions/units#degree +#define LV2_UNITS__frame LV2_UNITS_PREFIX "frame" ///< http://lv2plug.in/ns/extensions/units#frame +#define LV2_UNITS__hz LV2_UNITS_PREFIX "hz" ///< http://lv2plug.in/ns/extensions/units#hz +#define LV2_UNITS__inch LV2_UNITS_PREFIX "inch" ///< http://lv2plug.in/ns/extensions/units#inch +#define LV2_UNITS__khz LV2_UNITS_PREFIX "khz" ///< http://lv2plug.in/ns/extensions/units#khz +#define LV2_UNITS__km LV2_UNITS_PREFIX "km" ///< http://lv2plug.in/ns/extensions/units#km +#define LV2_UNITS__m LV2_UNITS_PREFIX "m" ///< http://lv2plug.in/ns/extensions/units#m +#define LV2_UNITS__mhz LV2_UNITS_PREFIX "mhz" ///< http://lv2plug.in/ns/extensions/units#mhz +#define LV2_UNITS__midiNote LV2_UNITS_PREFIX "midiNote" ///< http://lv2plug.in/ns/extensions/units#midiNote +#define LV2_UNITS__mile LV2_UNITS_PREFIX "mile" ///< http://lv2plug.in/ns/extensions/units#mile +#define LV2_UNITS__min LV2_UNITS_PREFIX "min" ///< http://lv2plug.in/ns/extensions/units#min +#define LV2_UNITS__mm LV2_UNITS_PREFIX "mm" ///< http://lv2plug.in/ns/extensions/units#mm +#define LV2_UNITS__ms LV2_UNITS_PREFIX "ms" ///< http://lv2plug.in/ns/extensions/units#ms +#define LV2_UNITS__name LV2_UNITS_PREFIX "name" ///< http://lv2plug.in/ns/extensions/units#name +#define LV2_UNITS__oct LV2_UNITS_PREFIX "oct" ///< http://lv2plug.in/ns/extensions/units#oct +#define LV2_UNITS__pc LV2_UNITS_PREFIX "pc" ///< http://lv2plug.in/ns/extensions/units#pc +#define LV2_UNITS__prefixConversion LV2_UNITS_PREFIX "prefixConversion" ///< http://lv2plug.in/ns/extensions/units#prefixConversion +#define LV2_UNITS__render LV2_UNITS_PREFIX "render" ///< http://lv2plug.in/ns/extensions/units#render +#define LV2_UNITS__s LV2_UNITS_PREFIX "s" ///< http://lv2plug.in/ns/extensions/units#s +#define LV2_UNITS__semitone12TET LV2_UNITS_PREFIX "semitone12TET" ///< http://lv2plug.in/ns/extensions/units#semitone12TET +#define LV2_UNITS__symbol LV2_UNITS_PREFIX "symbol" ///< http://lv2plug.in/ns/extensions/units#symbol +#define LV2_UNITS__unit LV2_UNITS_PREFIX "unit" ///< http://lv2plug.in/ns/extensions/units#unit + +// clang-format on + +/** + @} +*/ + +#endif /* LV2_UNITS_H */ diff --git a/include/lv2/uri-map/uri-map.h b/include/lv2/uri-map/uri-map.h new file mode 100644 index 0000000..47cde1c --- /dev/null +++ b/include/lv2/uri-map/uri-map.h @@ -0,0 +1,121 @@ +/* + Copyright 2008-2016 David Robillard <d@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. +*/ + +#ifndef LV2_URI_MAP_H +#define LV2_URI_MAP_H + +/** + @defgroup uri-map URI Map + @ingroup lv2 + + A feature for mapping URIs to integers. + + 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). + + See <http://lv2plug.in/ns/ext/uri-map> for details. + + @{ +*/ + +// clang-format off + +#define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map" ///< http://lv2plug.in/ns/ext/uri-map +#define LV2_URI_MAP_PREFIX LV2_URI_MAP_URI "#" ///< http://lv2plug.in/ns/ext/uri-map# + +// clang-format on + +#include "lv2/core/attributes.h" + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +LV2_DISABLE_DEPRECATION_WARNINGS + +/** + Opaque pointer to host data. +*/ +LV2_DEPRECATED +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. +*/ +LV2_DEPRECATED +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; + +LV2_RESTORE_WARNINGS + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/** + @} +*/ + +#endif /* LV2_URI_MAP_H */ diff --git a/include/lv2/urid/urid.h b/include/lv2/urid/urid.h new file mode 100644 index 0000000..b537d14 --- /dev/null +++ b/include/lv2/urid/urid.h @@ -0,0 +1,140 @@ +/* + Copyright 2008-2016 David Robillard <d@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. +*/ + +#ifndef LV2_URID_H +#define LV2_URID_H + +/** + @defgroup urid URID + @ingroup lv2 + + Features for mapping URIs to and from integers. + + See <http://lv2plug.in/ns/ext/urid> for details. + + @{ +*/ + +// clang-format off + +#define LV2_URID_URI "http://lv2plug.in/ns/ext/urid" ///< http://lv2plug.in/ns/ext/urid +#define LV2_URID_PREFIX LV2_URID_URI "#" ///< http://lv2plug.in/ns/ext/urid# + +#define LV2_URID__map LV2_URID_PREFIX "map" ///< http://lv2plug.in/ns/ext/urid#map +#define LV2_URID__unmap LV2_URID_PREFIX "unmap" ///< http://lv2plug.in/ns/ext/urid#unmap + +#define LV2_URID_MAP_URI LV2_URID__map ///< Legacy +#define LV2_URID_UNMAP_URI LV2_URID__unmap ///< Legacy + +// clang-format on + +#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 { + /** + 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 { + /** + 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 */ diff --git a/include/lv2/worker/worker.h b/include/lv2/worker/worker.h new file mode 100644 index 0000000..4fd89f9 --- /dev/null +++ b/include/lv2/worker/worker.h @@ -0,0 +1,183 @@ +/* + Copyright 2012-2016 David Robillard <d@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. +*/ + +#ifndef LV2_WORKER_H +#define LV2_WORKER_H + +/** + @defgroup worker Worker + @ingroup lv2 + + Support for non-realtime plugin operations. + + See <http://lv2plug.in/ns/ext/worker> for details. + + @{ +*/ + +#include "lv2/core/lv2.h" + +#include <stdint.h> + +// clang-format off + +#define LV2_WORKER_URI "http://lv2plug.in/ns/ext/worker" ///< http://lv2plug.in/ns/ext/worker +#define LV2_WORKER_PREFIX LV2_WORKER_URI "#" ///< http://lv2plug.in/ns/ext/worker# + +#define LV2_WORKER__interface LV2_WORKER_PREFIX "interface" ///< http://lv2plug.in/ns/ext/worker#interface +#define LV2_WORKER__schedule LV2_WORKER_PREFIX "schedule" ///< http://lv2plug.in/ns/ext/worker#schedule + +// clang-format on + +#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 { + /** + 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 { + /** + 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 (for example, during 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 */ |