13
0

Update to latest LV2 atom extension.

Implement proper support for fixed size LV2 plugin UIs.


git-svn-id: svn://localhost/ardour2/branches/3.0@11757 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2012-03-25 17:17:40 +00:00
parent d8ee15df1a
commit 1716dc0ce6
8 changed files with 342 additions and 245 deletions

View File

@ -327,6 +327,12 @@ LV2PluginUI::get_preferred_width()
return r.width;
}
bool
LV2PluginUI::resizable()
{
return _lv2->ui_is_resizable();
}
int
LV2PluginUI::package(Gtk::Window& win)
{

View File

@ -53,6 +53,8 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
gint get_preferred_height ();
gint get_preferred_width ();
bool resizable ();
bool start_updating(GdkEventAny*);
bool stop_updating(GdkEventAny*);

View File

@ -159,6 +159,7 @@ PluginUIWindow::PluginUIWindow (
}
set_default_size (w, h);
set_resizable (_pluginui->resizable());
}
PluginUIWindow::~PluginUIWindow ()

View File

@ -85,6 +85,7 @@ class PlugUIBase : public virtual sigc::trackable, public PBD::ScopedConnectionL
virtual gint get_preferred_height () = 0;
virtual gint get_preferred_width () = 0;
virtual bool resizable () { return true; }
virtual bool start_updating(GdkEventAny*) = 0;
virtual bool stop_updating(GdkEventAny*) = 0;

View File

@ -65,6 +65,7 @@ class LV2Plugin : public ARDOUR::Plugin
void* c_ui_type();
bool is_external_ui () const;
bool ui_is_resizable () const;
const char* port_symbol (uint32_t port) const;

View File

@ -25,42 +25,42 @@
#include <stdint.h>
#include <stddef.h>
#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
#define LV2_ATOM_PREFIX LV2_ATOM_URI "#"
#define LV2_ATOM__Atom LV2_ATOM_URI "#Atom"
#define LV2_ATOM__AtomPort LV2_ATOM_URI "#AtomPort"
#define LV2_ATOM__AudioFrames LV2_ATOM_URI "#AudioFrames"
#define LV2_ATOM__Beats LV2_ATOM_URI "#Beats"
#define LV2_ATOM__Blank LV2_ATOM_URI "#Blank"
#define LV2_ATOM__Bool LV2_ATOM_URI "#Bool"
#define LV2_ATOM__Chunk LV2_ATOM_URI "#Chunk"
#define LV2_ATOM__Double LV2_ATOM_URI "#Double"
#define LV2_ATOM__Event LV2_ATOM_URI "#Event"
#define LV2_ATOM__Float LV2_ATOM_URI "#Float"
#define LV2_ATOM__Int32 LV2_ATOM_URI "#Int32"
#define LV2_ATOM__Int64 LV2_ATOM_URI "#Int64"
#define LV2_ATOM__Literal LV2_ATOM_URI "#Literal"
#define LV2_ATOM__MessagePort LV2_ATOM_URI "#MessagePort"
#define LV2_ATOM__Number LV2_ATOM_URI "#Number"
#define LV2_ATOM__Object LV2_ATOM_URI "#Object"
#define LV2_ATOM__Path LV2_ATOM_URI "#Path"
#define LV2_ATOM__Property LV2_ATOM_URI "#Property"
#define LV2_ATOM__Resource LV2_ATOM_URI "#Resource"
#define LV2_ATOM__Sequence LV2_ATOM_URI "#Sequence"
#define LV2_ATOM__String LV2_ATOM_URI "#String"
#define LV2_ATOM__TimeUnit LV2_ATOM_URI "#TimeUnit"
#define LV2_ATOM__Tuple LV2_ATOM_URI "#Tuple"
#define LV2_ATOM__URI LV2_ATOM_URI "#URI"
#define LV2_ATOM__URID LV2_ATOM_URI "#URID"
#define LV2_ATOM__ValuePort LV2_ATOM_URI "#ValuePort"
#define LV2_ATOM__Vector LV2_ATOM_URI "#Vector"
#define LV2_ATOM__beatTime LV2_ATOM_URI "#beatTime"
#define LV2_ATOM__bufferType LV2_ATOM_URI "#bufferType"
#define LV2_ATOM__childType LV2_ATOM_URI "#childType"
#define LV2_ATOM__eventTransfer LV2_ATOM_URI "#eventTransfer"
#define LV2_ATOM__frameTime LV2_ATOM_URI "#frameTime"
#define LV2_ATOM__supports LV2_ATOM_URI "#supports"
#define LV2_ATOM__timeUnit LV2_ATOM_URI "#timeUnit"
#define LV2_ATOM__Atom LV2_ATOM_PREFIX "Atom"
#define LV2_ATOM__AtomPort LV2_ATOM_PREFIX "AtomPort"
#define LV2_ATOM__AudioFrames LV2_ATOM_PREFIX "AudioFrames"
#define LV2_ATOM__Beats LV2_ATOM_PREFIX "Beats"
#define LV2_ATOM__Blank LV2_ATOM_PREFIX "Blank"
#define LV2_ATOM__Bool LV2_ATOM_PREFIX "Bool"
#define LV2_ATOM__Chunk LV2_ATOM_PREFIX "Chunk"
#define LV2_ATOM__Double LV2_ATOM_PREFIX "Double"
#define LV2_ATOM__Event LV2_ATOM_PREFIX "Event"
#define LV2_ATOM__Float LV2_ATOM_PREFIX "Float"
#define LV2_ATOM__Int LV2_ATOM_PREFIX "Int"
#define LV2_ATOM__Long LV2_ATOM_PREFIX "Long"
#define LV2_ATOM__Literal LV2_ATOM_PREFIX "Literal"
#define LV2_ATOM__Number LV2_ATOM_PREFIX "Number"
#define LV2_ATOM__Object LV2_ATOM_PREFIX "Object"
#define LV2_ATOM__Path LV2_ATOM_PREFIX "Path"
#define LV2_ATOM__Property LV2_ATOM_PREFIX "Property"
#define LV2_ATOM__Resource LV2_ATOM_PREFIX "Resource"
#define LV2_ATOM__Sequence LV2_ATOM_PREFIX "Sequence"
#define LV2_ATOM__Sound LV2_ATOM_PREFIX "Sound"
#define LV2_ATOM__String LV2_ATOM_PREFIX "String"
#define LV2_ATOM__TimeUnit LV2_ATOM_PREFIX "TimeUnit"
#define LV2_ATOM__Tuple LV2_ATOM_PREFIX "Tuple"
#define LV2_ATOM__URI LV2_ATOM_PREFIX "URI"
#define LV2_ATOM__URID LV2_ATOM_PREFIX "URID"
#define LV2_ATOM__Vector LV2_ATOM_PREFIX "Vector"
#define LV2_ATOM__beatTime LV2_ATOM_PREFIX "beatTime"
#define LV2_ATOM__bufferType LV2_ATOM_PREFIX "bufferType"
#define LV2_ATOM__childType LV2_ATOM_PREFIX "childType"
#define LV2_ATOM__eventTransfer LV2_ATOM_PREFIX "eventTransfer"
#define LV2_ATOM__frameTime LV2_ATOM_PREFIX "frameTime"
#define LV2_ATOM__supports LV2_ATOM_PREFIX "supports"
#define LV2_ATOM__timeUnit LV2_ATOM_PREFIX "timeUnit"
#define LV2_ATOM_REFERENCE_TYPE 0
@ -93,23 +93,17 @@ typedef struct {
uint32_t type; /**< Type of this atom (mapped URI). */
} LV2_Atom;
/** A chunk of memory that may be uninitialized or contain an Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom body; /**< Body atom header. */
} LV2_Atom_Chunk;
/** An atom:Int32 or atom:Bool. May be cast to 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_Int32;
} LV2_Atom_Int;
/** An atom:Int64. May be cast to LV2_Atom. */
/** An atom:Long. May be cast to LV2_Atom. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
int64_t body; /**< Integer value. */
} LV2_Atom_Int64;
} LV2_Atom_Long;
/** An atom:Float. May be cast to LV2_Atom. */
typedef struct {
@ -124,7 +118,7 @@ typedef struct {
} LV2_Atom_Double;
/** An atom:Bool. May be cast to LV2_Atom. */
typedef LV2_Atom_Int32 LV2_Atom_Bool;
typedef LV2_Atom_Int LV2_Atom_Bool;
/** An atom:URID. May be cast to LV2_Atom. */
typedef struct {
@ -159,8 +153,8 @@ typedef struct {
/** The body of an atom:Vector. */
typedef struct {
uint32_t elem_count; /**< The number of elements in the vector */
uint32_t elem_type; /**< The type of each element in the vector */
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;
@ -233,8 +227,8 @@ typedef struct {
/** An atom:Sequence. */
typedef struct {
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Literal_Body body; /**< Body. */
LV2_Atom atom; /**< Atom header. */
LV2_Atom_Sequence_Body body; /**< Body. */
} LV2_Atom_Sequence;
#ifdef __cplusplus

View File

@ -57,15 +57,24 @@ extern "C" {
/** 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 void* (*LV2_Atom_Forge_Sink)(LV2_Atom_Forge_Sink_Handle handle,
const void* buf,
uint32_t size);
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* atom;
LV2_Atom_Forge_Ref ref;
} LV2_Atom_Forge_Frame;
/** A "forge" for creating atoms by appending to a buffer. */
@ -75,6 +84,7 @@ typedef struct {
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;
@ -83,8 +93,8 @@ typedef struct {
LV2_URID Bool;
LV2_URID Double;
LV2_URID Float;
LV2_URID Int32;
LV2_URID Int64;
LV2_URID Int;
LV2_URID Long;
LV2_URID Literal;
LV2_URID Path;
LV2_URID Property;
@ -97,66 +107,8 @@ typedef struct {
LV2_URID Vector;
} LV2_Atom_Forge;
/**
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*
lv2_atom_forge_push(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_Atom* atom)
{
frame->parent = forge->stack;
frame->atom = atom;
forge->stack = frame;
return atom;
}
/** 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)
{
assert(frame == forge->stack);
forge->stack = frame->parent;
}
/** Set the output buffer where @p 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 = size;
forge->offset = 0;
forge->sink = NULL;
forge->handle = NULL;
forge->stack = NULL;
}
/**
Set the sink function where @p forge will write output.
The return value of forge functions is a pointer to the written data, which
is used for updating parent sizes. To enable this, the sink function must
return a valid pointer to a contiguous LV2_Atom header. 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. When using a ringbuffer,
the returned pointers may not point to a complete atom (including body).
The user must take care to only use these return values in a way compatible
with the sink used.
*/
static inline void
lv2_atom_forge_set_sink(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Sink sink,
LV2_Atom_Forge_Sink_Handle handle)
{
forge->buf = NULL;
forge->size = forge->offset = 0;
forge->sink = sink;
forge->handle = handle;
forge->stack = NULL;
}
lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size);
/**
Initialise @p forge.
@ -168,48 +120,147 @@ static inline void
lv2_atom_forge_init(LV2_Atom_Forge* forge, LV2_URID_Map* map)
{
lv2_atom_forge_set_buffer(forge, NULL, 0);
forge->stack = NULL;
forge->Blank = map->map(map->handle, LV2_ATOM_URI "#Blank");
forge->Bool = map->map(map->handle, LV2_ATOM_URI "#Bool");
forge->Double = map->map(map->handle, LV2_ATOM_URI "#Double");
forge->Float = map->map(map->handle, LV2_ATOM_URI "#Float");
forge->Int32 = map->map(map->handle, LV2_ATOM_URI "#Int32");
forge->Int64 = map->map(map->handle, LV2_ATOM_URI "#Int64");
forge->Literal = map->map(map->handle, LV2_ATOM_URI "#Literal");
forge->Path = map->map(map->handle, LV2_ATOM_URI "#Path");
forge->Property = map->map(map->handle, LV2_ATOM_URI "#Property");
forge->Resource = map->map(map->handle, LV2_ATOM_URI "#Resource");
forge->Sequence = map->map(map->handle, LV2_ATOM_URI "#Sequence");
forge->String = map->map(map->handle, LV2_ATOM_URI "#String");
forge->Tuple = map->map(map->handle, LV2_ATOM_URI "#Tuple");
forge->URI = map->map(map->handle, LV2_ATOM_URI "#URI");
forge->URID = map->map(map->handle, LV2_ATOM_URI "#URID");
forge->Vector = map->map(map->handle, LV2_ATOM_URI "#Vector");
forge->Blank = map->map(map->handle, LV2_ATOM__Blank);
forge->Bool = map->map(map->handle, LV2_ATOM__Bool);
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->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);
}
static inline LV2_Atom*
lv2_atom_forge_deref(LV2_Atom_Forge* forge, LV2_Atom_Forge_Ref ref)
{
if (forge->buf) {
return (LV2_Atom*)ref;
} else {
return 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;
forge->stack = frame;
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)
{
assert(frame == forge->stack);
forge->stack = frame->parent;
}
/** 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 &&
lv2_atom_forge_deref(forge, forge->stack->ref)->type == type;
}
/**
@}
@name Output Configuration
@{
*/
/** Set the output buffer where @p 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 = size;
forge->offset = 0;
forge->deref = NULL;
forge->sink = NULL;
forge->handle = NULL;
forge->stack = NULL;
}
/**
Set the sink function where @p 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 approriately padded.
*/
static inline void*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_raw(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
uint8_t* out = NULL;
LV2_Atom_Forge_Ref out = 0;
if (forge->sink) {
out = (uint8_t*)forge->sink(forge->handle, data, size);
out = forge->sink(forge->handle, data, size);
} else {
out = forge->buf + forge->offset;
out = (LV2_Atom_Forge_Ref)forge->buf + forge->offset;
uint8_t* mem = forge->buf + forge->offset;
if (forge->offset + size > forge->size) {
return NULL;
return 0;
}
forge->offset += size;
memcpy(out, data, size);
memcpy(mem, data, size);
}
if (out) {
for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) {
f->atom->size += size;
}
for (LV2_Atom_Forge_Frame* f = forge->stack; f; f = f->parent) {
lv2_atom_forge_deref(forge, f->ref)->size += size;
}
return out;
}
@ -224,109 +275,124 @@ lv2_atom_forge_pad(LV2_Atom_Forge* forge, uint32_t written)
}
/** Write raw output, padding to 64-bits as necessary. */
static inline void*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_write(LV2_Atom_Forge* forge, const void* data, uint32_t size)
{
void* out = lv2_atom_forge_raw(forge, data, 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*
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*)lv2_atom_forge_raw(forge, &a, sizeof(a));
return lv2_atom_forge_raw(forge, &a, sizeof(a));
}
/** Write an atom:Int32. */
static inline LV2_Atom_Int32*
lv2_atom_forge_int32(LV2_Atom_Forge* forge, int32_t val)
/** Write a primitive (fixed-size) atom. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_primitive(LV2_Atom_Forge* forge, const LV2_Atom* a)
{
const LV2_Atom_Int32 a = { { sizeof(val), forge->Int32 }, val };
return (LV2_Atom_Int32*)lv2_atom_forge_write(forge, &a, sizeof(a));
if (lv2_atom_forge_top_is(forge, forge->Vector)) {
return lv2_atom_forge_raw(forge, LV2_ATOM_BODY(a), a->size);
} else {
return lv2_atom_forge_write(forge, a, sizeof(LV2_Atom) + a->size);
}
}
/** Write an atom:Int64. */
static inline LV2_Atom_Int64*
lv2_atom_forge_int64(LV2_Atom_Forge* forge, int64_t val)
/** Write an atom:Int. */
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_int(LV2_Atom_Forge* forge, int32_t val)
{
const LV2_Atom_Int64 a = { { sizeof(val), forge->Int64 }, val };
return (LV2_Atom_Int64*)lv2_atom_forge_write(forge, &a, sizeof(a));
const LV2_Atom_Int a = { { sizeof(val), forge->Int }, val };
return lv2_atom_forge_primitive(forge, &a.atom);
}
/** 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, &a.atom);
}
/** Write an atom:Float. */
static inline LV2_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_Float*)lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_primitive(forge, &a.atom);
}
/** Write an atom:Double. */
static inline LV2_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_Double*)lv2_atom_forge_write(
forge, &a, sizeof(a));
return lv2_atom_forge_primitive(forge, &a.atom);
}
/** Write an atom:Bool. */
static inline LV2_Atom_Bool*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_bool(LV2_Atom_Forge* forge, bool val)
{
const LV2_Atom_Bool a = { { sizeof(val), forge->Bool }, val };
return (LV2_Atom_Bool*)lv2_atom_forge_write(forge, &a, sizeof(a));
const LV2_Atom_Bool a = { { sizeof(int32_t), forge->Bool }, val ? 1 : 0 };
return lv2_atom_forge_primitive(forge, &a.atom);
}
/** Write an atom:URID. */
static inline LV2_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_URID*)lv2_atom_forge_write(forge, &a, sizeof(a));
}
/** Write a string body. Used internally. */
static inline uint8_t*
lv2_atom_forge_string_body(LV2_Atom_Forge* forge,
const uint8_t* str,
uint32_t len)
{
void* out = NULL;
if ( (out = lv2_atom_forge_raw(forge, str, len))
&& (out = lv2_atom_forge_raw(forge, "", 1))) {
lv2_atom_forge_pad(forge, len + 1);
}
return (uint8_t*)out;
return lv2_atom_forge_primitive(forge, &a.atom);
}
/** Write an atom compatible with atom:String. Used internally. */
static inline LV2_Atom_String*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_typed_string(LV2_Atom_Forge* forge,
uint32_t type,
const uint8_t* str,
const char* str,
uint32_t len)
{
const LV2_Atom_String a = { { len + 1, type } };
LV2_Atom_String* out = (LV2_Atom_String*)
lv2_atom_forge_raw(forge, &a, sizeof(a));
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)) {
out->atom.size = out->atom.type = 0;
out = NULL;
LV2_Atom* atom = lv2_atom_forge_deref(forge, out);
atom->size = atom->type = 0;
out = 0;
}
}
return out;
}
/** Write an atom:String. Note that @p str need not be NULL terminated. */
static inline LV2_Atom_String*
lv2_atom_forge_string(LV2_Atom_Forge* forge, const uint8_t* str, uint32_t len)
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);
}
@ -336,23 +402,23 @@ lv2_atom_forge_string(LV2_Atom_Forge* forge, const uint8_t* str, uint32_t len)
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_String*
lv2_atom_forge_uri(LV2_Atom_Forge* forge, const uint8_t* uri, uint32_t len)
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 @p path need not be NULL terminated. */
static inline LV2_Atom_String*
lv2_atom_forge_path(LV2_Atom_Forge* forge, const uint8_t* path, uint32_t len)
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_Literal*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_literal(LV2_Atom_Forge* forge,
const uint8_t* str,
const char* str,
uint32_t len,
uint32_t datatype,
uint32_t lang)
@ -363,44 +429,47 @@ lv2_atom_forge_literal(LV2_Atom_Forge* forge,
{ datatype,
lang }
};
LV2_Atom_Literal* out = (LV2_Atom_Literal*)
lv2_atom_forge_raw(forge, &a, sizeof(a));
LV2_Atom_Forge_Ref out = lv2_atom_forge_raw(forge, &a, sizeof(a));
if (out) {
if (!lv2_atom_forge_string_body(forge, str, len)) {
out->atom.size = out->atom.type = 0;
out = NULL;
LV2_Atom* atom = lv2_atom_forge_deref(forge, out);
atom->size = atom->type = 0;
out = 0;
}
}
return out;
}
/** Write an atom:Vector header, but not the vector body. */
static inline LV2_Atom_Vector*
lv2_atom_forge_vector_head(LV2_Atom_Forge* forge,
uint32_t elem_count,
uint32_t elem_type,
uint32_t elem_size)
/** 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 uint32_t size = sizeof(LV2_Atom_Vector) + (elem_size * elem_count);
const LV2_Atom_Vector a = {
{ size - sizeof(LV2_Atom), forge->Vector },
{ elem_count, elem_type }
{ sizeof(LV2_Atom_Vector_Body), forge->Vector },
{ child_size, child_type }
};
return (LV2_Atom_Vector*)lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}
/** Write a complete atom:Vector. */
static inline LV2_Atom_Vector*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_vector(LV2_Atom_Forge* forge,
uint32_t elem_count,
uint32_t elem_type,
uint32_t elem_size,
void* elems)
uint32_t child_size,
uint32_t child_type,
uint32_t n_elems,
const void* elems)
{
LV2_Atom_Vector* out = lv2_atom_forge_vector_head(
forge, elem_count, elem_type, elem_size);
const LV2_Atom_Vector a = {
{ 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, elem_size * elem_count);
lv2_atom_forge_write(forge, elems, child_size * n_elems);
}
return out;
}
@ -422,12 +491,12 @@ lv2_atom_forge_vector(LV2_Atom_Forge* forge,
lv2_atom_forge_pop(forge, &frame);
@endcode
*/
static inline LV2_Atom_Tuple*
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 } };
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Tuple*)lv2_atom_forge_push(forge, frame, atom);
const LV2_Atom_Tuple a = { { 0, forge->Tuple } };
return lv2_atom_forge_push(
forge, frame, lv2_atom_forge_write(forge, &a, sizeof(a)));
}
/**
@ -444,7 +513,7 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
// Write object header
LV2_Atom_Forge_Frame frame;
LV2_Atom* obj = (LV2_Atom*)lv2_atom_forge_resource(forge, &frame, 1, eg_Cat);
lv2_atom_forge_resource(forge, &frame, 1, eg_Cat);
// Write property: eg:name = "Hobbes"
lv2_atom_forge_property_head(forge, eg_name, 0);
@ -454,7 +523,7 @@ lv2_atom_forge_tuple(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
lv2_atom_forge_pop(forge, &frame);
@endcode
*/
static inline LV2_Atom_Object*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_resource(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
LV2_URID id,
@ -464,14 +533,14 @@ lv2_atom_forge_resource(LV2_Atom_Forge* forge,
{ sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Resource },
{ id, otype }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Object*)lv2_atom_forge_push(forge, frame, atom);
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}
/**
The same as lv2_atom_forge_resource(), but for object:Blank.
*/
static inline LV2_Atom_Object*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_blank(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
uint32_t id,
@ -481,22 +550,21 @@ lv2_atom_forge_blank(LV2_Atom_Forge* forge,
{ sizeof(LV2_Atom_Object) - sizeof(LV2_Atom), forge->Blank },
{ id, otype }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Object*)lv2_atom_forge_push(forge, frame, atom);
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}
/**
Write the header for a property body (likely in an Object).
See lv2_atom_forge_object() documentation for an example.
*/
static inline LV2_Atom_Property_Body*
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_Property_Body*)lv2_atom_forge_write(
forge, &a, 2 * sizeof(uint32_t));
return lv2_atom_forge_write(forge, &a, 2 * sizeof(uint32_t));
}
/**
@ -504,7 +572,7 @@ lv2_atom_forge_property_head(LV2_Atom_Forge* forge,
The size of the returned sequence will be 0, so passing it as the parent
parameter to other forge methods will do the right thing.
*/
static inline LV2_Atom_Sequence*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
uint32_t unit)
@ -513,8 +581,8 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
{ sizeof(LV2_Atom_Sequence) - sizeof(LV2_Atom), forge->Sequence },
{ unit, 0 }
};
LV2_Atom* atom = (LV2_Atom*)lv2_atom_forge_write(forge, &a, sizeof(a));
return (LV2_Atom_Sequence*)lv2_atom_forge_push(forge, frame, atom);
LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a));
return lv2_atom_forge_push(forge, frame, out);
}
/**
@ -522,10 +590,10 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge,
After this, call the appropriate forge method(s) to write the body, passing
the same @p parent parameter. Note the returned LV2_Event is NOT an Atom.
*/
static inline int64_t*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames)
{
return (int64_t*)lv2_atom_forge_write(forge, &frames, sizeof(frames));
return lv2_atom_forge_write(forge, &frames, sizeof(frames));
}
/**
@ -533,12 +601,16 @@ lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames)
After this, call the appropriate forge method(s) to write the body, passing
the same @p parent parameter. Note the returned LV2_Event is NOT an Atom.
*/
static inline double*
static inline LV2_Atom_Forge_Ref
lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats)
{
return (double*)lv2_atom_forge_write(forge, &beats, sizeof(beats));
return lv2_atom_forge_write(forge, &beats, sizeof(beats));
}
/**
@}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -90,8 +90,8 @@ public:
LilvWorld* world;
LilvNode* atom_AtomPort;
LilvNode* atom_Chunk;
LilvNode* atom_MessagePort;
LilvNode* atom_Sequence;
LilvNode* atom_bufferType;
LilvNode* atom_eventTransfer;
@ -101,11 +101,11 @@ public:
LilvNode* lv2_ControlPort;
LilvNode* lv2_InputPort;
LilvNode* lv2_OutputPort;
LilvNode* lv2_enumeration;
LilvNode* lv2_inPlaceBroken;
LilvNode* lv2_integer;
LilvNode* lv2_sampleRate;
LilvNode* lv2_toggled;
LilvNode* lv2_enumeration;
LilvNode* midi_MidiEvent;
LilvNode* ui_GtkUI;
LilvNode* ui_external;
@ -253,7 +253,7 @@ LV2Plugin::init(void* c_plugin, framecnt_t rate)
flags |= PORT_AUDIO;
} else if (lilv_port_is_a(_impl->plugin, port, _world.ev_EventPort)) {
flags |= PORT_EVENT;
} else if (lilv_port_is_a(_impl->plugin, port, _world.atom_MessagePort)) {
} else if (lilv_port_is_a(_impl->plugin, port, _world.atom_AtomPort)) {
LilvNodes* buffer_types = lilv_port_get_value(
_impl->plugin, port, _world.atom_bufferType);
if (lilv_nodes_contains(buffer_types, _world.atom_Sequence)) {
@ -386,6 +386,26 @@ LV2Plugin::is_external_ui() const
return lilv_ui_is_a(_impl->ui, _world.ui_external);
}
bool
LV2Plugin::ui_is_resizable () const
{
const LilvNode* s = lilv_ui_get_uri(_impl->ui);
LilvNode* p = lilv_new_uri(_world.world, NS_UI "optionalFeature");
LilvNode* fs = lilv_new_uri(_world.world, NS_UI "fixedSize");
LilvNode* nrs = lilv_new_uri(_world.world, NS_UI "noUserResize");
LilvNodes* fs_matches = lilv_world_find_nodes(_world.world, s, p, fs);
LilvNodes* nrs_matches = lilv_world_find_nodes(_world.world, s, p, nrs);
lilv_nodes_free(nrs_matches);
lilv_nodes_free(fs_matches);
lilv_node_free(nrs);
lilv_node_free(fs);
lilv_node_free(p);
return !fs_matches && !nrs_matches;
}
string
LV2Plugin::unique_id() const
{
@ -1324,8 +1344,8 @@ LV2World::LV2World()
: world(lilv_world_new())
{
lilv_world_load_all(world);
atom_AtomPort = lilv_new_uri(world, LV2_ATOM__AtomPort);
atom_Chunk = lilv_new_uri(world, LV2_ATOM__Chunk);
atom_MessagePort = lilv_new_uri(world, LV2_ATOM__MessagePort);
atom_Sequence = lilv_new_uri(world, LV2_ATOM__Sequence);
atom_bufferType = lilv_new_uri(world, LV2_ATOM__bufferType);
atom_eventTransfer = lilv_new_uri(world, LV2_ATOM__eventTransfer);
@ -1363,8 +1383,8 @@ LV2World::~LV2World()
lilv_node_free(atom_eventTransfer);
lilv_node_free(atom_bufferType);
lilv_node_free(atom_Sequence);
lilv_node_free(atom_MessagePort);
lilv_node_free(atom_Chunk);
lilv_node_free(atom_AtomPort);
}
LV2PluginInfo::LV2PluginInfo (void* c_plugin)
@ -1435,7 +1455,7 @@ LV2PluginInfo::discover()
lilv_plugin_get_num_ports_of_class(
p, _world.lv2_InputPort, _world.ev_EventPort, NULL)
+ lilv_plugin_get_num_ports_of_class(
p, _world.lv2_InputPort, _world.atom_MessagePort, NULL));
p, _world.lv2_InputPort, _world.atom_AtomPort, NULL));
info->n_outputs.set_audio(
lilv_plugin_get_num_ports_of_class(
@ -1444,7 +1464,7 @@ LV2PluginInfo::discover()
lilv_plugin_get_num_ports_of_class(
p, _world.lv2_OutputPort, _world.ev_EventPort, NULL)
+ lilv_plugin_get_num_ports_of_class(
p, _world.lv2_OutputPort, _world.atom_MessagePort, NULL));
p, _world.lv2_OutputPort, _world.atom_AtomPort, NULL));
info->unique_id = lilv_node_as_uri(lilv_plugin_get_uri(p));
info->index = 0; // Meaningless for LV2