summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/lv2_plugin_ui.cc6
-rw-r--r--gtk2_ardour/lv2_plugin_ui.h2
-rw-r--r--gtk2_ardour/plugin_ui.cc1
-rw-r--r--gtk2_ardour/plugin_ui.h1
-rw-r--r--libs/ardour/ardour/lv2_plugin.h1
-rw-r--r--libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h96
-rw-r--r--libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h372
-rw-r--r--libs/ardour/lv2_plugin.cc34
8 files changed, 305 insertions, 208 deletions
diff --git a/gtk2_ardour/lv2_plugin_ui.cc b/gtk2_ardour/lv2_plugin_ui.cc
index d014cddd10..7947a8e7bf 100644
--- a/gtk2_ardour/lv2_plugin_ui.cc
+++ b/gtk2_ardour/lv2_plugin_ui.cc
@@ -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)
{
diff --git a/gtk2_ardour/lv2_plugin_ui.h b/gtk2_ardour/lv2_plugin_ui.h
index d245ed31a1..e90b27cf8f 100644
--- a/gtk2_ardour/lv2_plugin_ui.h
+++ b/gtk2_ardour/lv2_plugin_ui.h
@@ -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*);
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index 272abcb831..b4a412aa3f 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -159,6 +159,7 @@ PluginUIWindow::PluginUIWindow (
}
set_default_size (w, h);
+ set_resizable (_pluginui->resizable());
}
PluginUIWindow::~PluginUIWindow ()
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
index a966ed3024..2f98a28f6d 100644
--- a/gtk2_ardour/plugin_ui.h
+++ b/gtk2_ardour/plugin_ui.h
@@ -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;
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 0cd3bbd2de..f0ce7f7fba 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -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;
diff --git a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h b/libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h
index 6287830eed..3c7bee812b 100644
--- a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h
+++ b/libs/ardour/lv2/lv2plug.in/ns/ext/atom/atom.h
@@ -25,42 +25,42 @@
#include <stdint.h>
#include <stddef.h>
-#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom"
-
-#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_URI "http://lv2plug.in/ns/ext/atom"
+#define LV2_ATOM_PREFIX LV2_ATOM_URI "#"
+
+#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
diff --git a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h b/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h
index f55cb0800c..ea5977e500 100644
--- a/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h
+++ b/libs/ardour/lv2/lv2plug.in/ns/ext/atom/forge.h
@@ -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,21 +107,67 @@ typedef struct {
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 @p forge.
+
+ URIs will be mapped using @p map and stored, a reference to @p 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->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*
+static inline LV2_Atom_Forge_Ref
lv2_atom_forge_push(LV2_Atom_Forge* forge,
LV2_Atom_Forge_Frame* frame,
- LV2_Atom* atom)
+ LV2_Atom_Forge_Ref ref)
{
frame->parent = forge->stack;
- frame->atom = atom;
+ frame->ref = ref;
forge->stack = frame;
- return atom;
+ return ref;
}
/** Pop a stack frame. This must be called when a container is finished. */
@@ -122,6 +178,20 @@ lv2_atom_forge_pop(LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame)
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)
@@ -129,6 +199,7 @@ 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;
@@ -137,79 +208,59 @@ lv2_atom_forge_set_buffer(LV2_Atom_Forge* forge, uint8_t* buf, size_t size)
/**
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.
+ 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;
}
/**
- Initialise @p forge.
-
- URIs will be mapped using @p map and stored, a reference to @p map itself is
- not held.
+ @}
+ @name Low Level Output
+ @{
*/
-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");
-}
/**
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
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index a12241b776..6a41463114 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -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