aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2017-07-05 22:42:18 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2017-07-05 22:42:18 +0200
commit0dd808ef00c5e2a203c51ff3872d71b7897f7458 (patch)
tree56d168da1e3b83c3aece0292f7b1ca82a3f38ed1
parent28e396adb8d82630fc7f6b5b141b47f2c4deab41 (diff)
downloadsherlock.lv2-0dd808ef00c5e2a203c51ff3872d71b7897f7458.tar.xz
Squashed 'props.lv2/' changes from 28e396a..70700f5
70700f5 simplify API. d527385 use log extension. e829935 add magic header to check for props worker jobs. 914a279 fix qsort. e999146 prototype state worker. e452572 simplify API. 86459c0 migrate to branch-free bsearch implementation. 40846f6 implement patch:sequenceNumber/Ack/Error. 4de8ac9 fixes to pass sord_validate. 7c88c89 pack lv2:scalePoints into atom:Tuple. 3274e30 add missing <stdio.h> header. git-subtree-dir: props.lv2 git-subtree-split: 70700f540754b9ffd18059ef9e94ff4745fd0dd3
-rw-r--r--props.h1254
-rw-r--r--test/props.c431
-rw-r--r--test/props.ttl8
3 files changed, 533 insertions, 1160 deletions
diff --git a/props.h b/props.h
index ebbc3ec..896bfd7 100644
--- a/props.h
+++ b/props.h
@@ -24,6 +24,7 @@ extern "C" {
#include <stdlib.h>
#include <stdatomic.h>
+#include <stdio.h>
#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
@@ -31,120 +32,49 @@ extern "C" {
#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
#include <lv2/lv2plug.in/ns/ext/patch/patch.h>
#include <lv2/lv2plug.in/ns/ext/state/state.h>
-#include <lv2/lv2plug.in/ns/extensions/units/units.h>
/*****************************************************************************
* API START
*****************************************************************************/
-// definitions
-#define PROPS_TYPE_N 10
-
-// unions
-typedef union _props_raw_t props_raw_t;
-
-// enumerations
-typedef enum _props_mode_t props_mode_t;
-typedef enum _props_event_t props_event_t;
-
// structures
-typedef struct _props_scale_point_t props_scale_point_t;
typedef struct _props_def_t props_def_t;
-typedef struct _props_type_t props_type_t;
typedef struct _props_impl_t props_impl_t;
typedef struct _props_t props_t;
// function callbacks
typedef void (*props_event_cb_t)(
void *data,
- LV2_Atom_Forge *forge,
int64_t frames,
- props_event_t event,
props_impl_t *impl);
-typedef uint32_t (*props_type_size_cb_t)(
- const void *value);
-
-typedef LV2_Atom_Forge_Ref (*props_type_get_cb_t)(
- LV2_Atom_Forge *forge,
- const void *value);
-
-typedef void (*props_type_set_cb_t)(
- props_impl_t *impl,
- void *value,
- LV2_URID new_type,
- uint32_t sz,
- const void *new_value);
-
-union _props_raw_t {
- const int32_t i; // Int
- const int64_t h; // Long
- const float f; // Float
- const double d; // Double
- const int32_t b; // Bool
- const uint32_t u; // URID
- //TODO more types
-};
-
-enum _props_mode_t {
- PROP_MODE_STATIC = 0,
- PROP_MODE_DYNAMIC = 1
-};
-
-enum _props_event_t {
- PROP_EVENT_GET = (1 << 0),
- PROP_EVENT_SET = (1 << 1),
- PROP_EVENT_SAVE = (1 << 2),
- PROP_EVENT_RESTORE = (1 << 3),
- PROP_EVENT_REGISTER = (1 << 4)
-};
-
-#define PROP_EVENT_NONE (0)
-#define PROP_EVENT_READ (PROP_EVENT_GET | PROP_EVENT_SAVE)
-#define PROP_EVENT_WRITE (PROP_EVENT_SET | PROP_EVENT_RESTORE)
-#define PROP_EVENT_RW (PROP_EVENT_READ | PROP_EVENT_WRITE)
-#define PROP_EVENT_ALL (PROP_EVENT_RW | PROP_EVENT_REGISTER)
-
-struct _props_scale_point_t {
- const char *label;
- props_raw_t value;
-};
-
struct _props_def_t {
const char *property;
const char *type;
const char *access;
- const char *unit;
- props_mode_t mode;
- props_event_t event_mask;
- props_event_cb_t event_cb;
- uint32_t max_size;
-
- const char *label;
- const char *comment;
- props_raw_t minimum;
- props_raw_t maximum;
- const props_scale_point_t *scale_points;
-};
+ size_t offset;
-struct _props_type_t {
- LV2_URID urid;
- uint32_t size;
- props_type_size_cb_t size_cb;
- props_type_get_cb_t get_cb;
- props_type_set_cb_t set_cb;
+ uint32_t max_size;
+ props_event_cb_t event_cb;
};
struct _props_impl_t {
LV2_URID property;
+ LV2_URID type;
LV2_URID access;
- LV2_URID unit;
- const props_t *props;
- const props_type_t *type;
+
+ struct {
+ uint32_t size;
+ void *body;
+ } value;
+ struct {
+ uint32_t size;
+ void *body;
+ } stash;
+
const props_def_t *def;
- void *value;
- void *stash;
- atomic_flag lock;
+
+ atomic_int state;
bool stashing;
};
@@ -165,16 +95,9 @@ struct _props_t {
LV2_URID patch_value;
LV2_URID patch_writable;
LV2_URID patch_readable;
-
- LV2_URID rdf_value;
-
- LV2_URID rdfs_label;
- LV2_URID rdfs_range;
- LV2_URID rdfs_comment;
-
- LV2_URID lv2_minimum;
- LV2_URID lv2_maximum;
- LV2_URID lv2_scale_point;
+ LV2_URID patch_sequence;
+ LV2_URID patch_error;
+ LV2_URID patch_ack;
LV2_URID atom_int;
LV2_URID atom_long;
@@ -182,23 +105,20 @@ struct _props_t {
LV2_URID atom_double;
LV2_URID atom_bool;
LV2_URID atom_urid;
- LV2_URID atom_string;
LV2_URID atom_path;
- LV2_URID atom_uri;
- LV2_URID atom_chunk;
-
- LV2_URID units_unit;
+ LV2_URID atom_literal;
+ LV2_URID atom_vector;
+ LV2_URID atom_object;
+ LV2_URID atom_sequence;
} urid;
- LV2_URID_Map *map;
void *data;
- props_type_t types [PROPS_TYPE_N];
-
bool stashing;
+ atomic_bool restoring;
+
+ uint32_t max_size;
- unsigned max_size;
- unsigned max_nimpls;
unsigned nimpls;
props_impl_t impls [0];
};
@@ -209,12 +129,15 @@ struct _props_t {
// rt-safe
static inline int
-props_init(props_t *props, const size_t max_nimpls, const char *subject,
+props_init(props_t *props, const char *subject,
+ const props_def_t *defs, int nimpls,
+ void *value_base, void *stash_base,
LV2_URID_Map *map, void *data);
// rt-safe
-static inline LV2_URID
-props_register(props_t *props, const props_def_t *def, void *value, void *stash);
+static inline void
+props_idle(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ LV2_Atom_Forge_Ref *ref);
// rt-safe
static inline int
@@ -223,371 +146,136 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
// rt-safe
static inline void
-props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, LV2_URID property,
- LV2_Atom_Forge_Ref *ref);
+props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ LV2_URID property, LV2_Atom_Forge_Ref *ref);
// rt-safe
static inline void
props_stash(props_t *props, LV2_URID property);
+// rt-safe
+static inline LV2_URID
+props_map(props_t *props, const char *property);
+
+// rt-safe
+static inline const char *
+props_unmap(props_t *props, LV2_URID property);
+
// non-rt
static inline LV2_State_Status
-props_save(props_t *props, LV2_Atom_Forge *forge, LV2_State_Store_Function store,
+props_save(props_t *props, LV2_State_Store_Function store,
LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features);
// non-rt
static inline LV2_State_Status
-props_restore(props_t *props, LV2_Atom_Forge *forge, LV2_State_Retrieve_Function retrieve,
+props_restore(props_t *props, LV2_State_Retrieve_Function retrieve,
LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features);
/*****************************************************************************
* API END
*****************************************************************************/
+// enumerations
+typedef enum _props_state_t props_state_t;
+
+enum _props_state_t {
+ PROP_STATE_NONE = 0,
+ PROP_STATE_LOCK = 1,
+ PROP_STATE_RESTORE = 2
+};
+
static inline void
-_impl_spin_lock(props_impl_t *impl)
+_props_impl_spin_lock(props_impl_t *impl, int from, int to)
{
- while(atomic_flag_test_and_set_explicit(&impl->lock, memory_order_acquire))
+ int expected = from;
+ const int desired = to;
+
+ while(!atomic_compare_exchange_strong_explicit(&impl->state, &expected, desired,
+ memory_order_acquire, memory_order_acquire))
{
// spin
}
}
static inline bool
-_impl_try_lock(props_impl_t *impl)
-{
- return atomic_flag_test_and_set_explicit(&impl->lock, memory_order_acquire) == false;
-}
-
-static inline void
-_impl_unlock(props_impl_t *impl)
+_props_impl_try_lock(props_impl_t *impl, int from, int to)
{
- atomic_flag_clear_explicit(&impl->lock, memory_order_release);
-}
-
-static inline uint32_t
-_impl_size_get(props_impl_t *impl)
-{
- return impl->type->size_cb
- ? impl->type->size_cb(impl->value)
- : impl->type->size;
-}
-
-static LV2_Atom_Forge_Ref
-_props_int_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_int(forge, *(const int32_t *)value);
-}
-static LV2_Atom_Forge_Ref
-_props_bool_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_bool(forge, *(const int32_t *)value);
-}
-static void
-_props_int_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
- int32_t *ref = value;
-
- if(new_type == props->urid.atom_int)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_bool)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_urid)
- *ref = *(const uint32_t *)new_value;
- else if(new_type == props->urid.atom_long)
- *ref = *(const int64_t *)new_value;
-
- else if(new_type == props->urid.atom_float)
- *ref = *(const float *)new_value;
- else if(new_type == props->urid.atom_double)
- *ref = *(const double *)new_value;
-}
-
-static LV2_Atom_Forge_Ref
-_props_long_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_long(forge, *(const int64_t *)value);
-}
-static void
-_props_long_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
- int64_t *ref = value;
-
- if(new_type == props->urid.atom_long)
- *ref = *(const int64_t *)new_value;
- else if(new_type == props->urid.atom_int)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_bool)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_urid)
- *ref = *(const uint32_t *)new_value;
-
- else if(new_type == props->urid.atom_float)
- *ref = *(const float *)new_value;
- else if(new_type == props->urid.atom_double)
- *ref = *(const double *)new_value;
-}
-
-static LV2_Atom_Forge_Ref
-_props_float_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_float(forge, *(const float *)value);
-}
-static void
-_props_float_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
- float *ref = value;
-
- if(new_type == props->urid.atom_float)
- *ref = *(const float *)new_value;
- else if(new_type == props->urid.atom_double)
- *ref = *(const double *)new_value;
-
- else if(new_type == props->urid.atom_int)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_bool)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_urid)
- *ref = *(const uint32_t *)new_value;
- else if(new_type == props->urid.atom_long)
- *ref = *(const int64_t *)new_value;
-}
-
-static LV2_Atom_Forge_Ref
-_props_double_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_double(forge, *(const double *)value);
-}
-static void
-_props_double_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
- double *ref = value;
-
- if(new_type == props->urid.atom_double)
- *ref = *(const double *)new_value;
- else if(new_type == props->urid.atom_float)
- *ref = *(const float *)new_value;
-
- else if(new_type == props->urid.atom_int)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_bool)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_urid)
- *ref = *(const uint32_t *)new_value;
- else if(new_type == props->urid.atom_long)
- *ref = *(const int64_t *)new_value;
-}
+ int expected = from;
+ const int desired = to;
-static LV2_Atom_Forge_Ref
-_props_urid_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_urid(forge, *(const uint32_t *)value);
-}
-static void
-_props_urid_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
- uint32_t *ref = value;
-
- if(new_type == props->urid.atom_urid)
- *ref = *(const uint32_t *)new_value;
-
- else if(new_type == props->urid.atom_int)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_long)
- *ref = *(const int64_t *)new_value;
- else if(new_type == props->urid.atom_bool)
- *ref = *(const int32_t *)new_value;
- else if(new_type == props->urid.atom_float)
- *ref = *(const float *)new_value;
- else if(new_type == props->urid.atom_double)
- *ref = *(const double *)new_value;
+ return atomic_compare_exchange_strong_explicit(&impl->state, &expected, desired,
+ memory_order_acquire, memory_order_acquire);
}
-static uint32_t
-_props_string_size_cb(const void *value)
-{
- return strlen((const char *)value) + 1;
-}
-static LV2_Atom_Forge_Ref
-_props_string_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_string(forge, (const char *)value, strlen((const char *)value));
-}
-static LV2_Atom_Forge_Ref
-_props_path_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_path(forge, (const char *)value, strlen((const char *)value));
-}
-static LV2_Atom_Forge_Ref
-_props_uri_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- return lv2_atom_forge_uri(forge, (const char *)value, strlen((const char *)value));
-}
-static void
-_props_string_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
-{
- const props_t *props = impl->props;
-
- if( (new_type == props->urid.atom_string)
- || (new_type == props->urid.atom_path)
- || (new_type == props->urid.atom_uri) )
- strncpy((char *)value, (const char *)new_value, impl->def->max_size);
-}
-
-static uint32_t
-_props_chunk_size_cb(const void *value)
+static inline void
+_props_impl_unlock(props_impl_t *impl, int to)
{
- const uint32_t sz = *(uint32_t *)value;
- return sz;
+ atomic_store_explicit(&impl->state, to, memory_order_release);
}
-static LV2_Atom_Forge_Ref
-_props_chunk_get_cb(LV2_Atom_Forge *forge, const void *value)
-{
- const uint32_t sz = *(uint32_t *)value;
- const uint8_t *src = value + sizeof(uint32_t);
- LV2_Atom_Forge_Ref ref;
- return (ref = lv2_atom_forge_atom(forge, sz, forge->Chunk))
- && (ref = lv2_atom_forge_write(forge, src, sz));
-}
-static void
-_props_chunk_set_cb(props_impl_t *impl, void *value,
- LV2_URID new_type, uint32_t sz, const void *new_value)
+static inline bool
+_props_restoring_get(props_t *props)
{
- const props_t *props = impl->props;
-
- if(new_type == props->urid.atom_chunk)
- {
- *(uint32_t *)value = sz; // set chunk size
- uint8_t *dst = value + sizeof(uint32_t);
- const uint32_t msz = sz < impl->def->max_size - sizeof(uint32_t)
- ? sz
- : impl->def->max_size - sizeof(uint32_t);
- memcpy(dst, new_value, msz);
- }
+ return atomic_exchange_explicit(&props->restoring, false, memory_order_acquire);
}
static inline void
-_type_qsort(props_type_t *a, unsigned n)
+_props_restoring_set(props_t *props)
{
- if(n < 2)
- return;
-
- const props_type_t *p = &a[n/2];
-
- unsigned i, j;
- for(i=0, j=n-1; ; i++, j--)
- {
- while(a[i].urid < p->urid)
- i++;
-
- while(p->urid < a[j].urid)
- j--;
-
- if(i >= j)
- break;
-
- const props_type_t t = a[i];
- a[i] = a[j];
- a[j] = t;
- }
-
- _type_qsort(a, i);
- _type_qsort(&a[i], n - i);
-}
-
-static inline props_type_t *
-_type_bsearch(LV2_URID p, props_type_t *a, unsigned n)
-{
- unsigned start = 0;
- unsigned end = n;
-
- while(start < end)
- {
- const unsigned mid = start + (end - start)/2;
- props_type_t *dst = &a[mid];
-
- if(p < dst->urid)
- end = mid;
- else if(p > dst->urid)
- start = mid + 1;
- else
- return dst;
- }
-
- return NULL;
+ atomic_store_explicit(&props->restoring, true, memory_order_release);
}
static inline void
-_impl_qsort(props_impl_t *a, unsigned n)
+_props_qsort(props_impl_t *A, int n)
{
if(n < 2)
return;
- const props_impl_t *p = &a[n/2];
+ const props_impl_t *p = A;
+
+ int i = -1;
+ int j = n;
- unsigned i, j;
- for(i=0, j=n-1; ; i++, j--)
+ while(true)
{
- while(a[i].property < p->property)
- i++;
+ do {
+ i += 1;
+ } while(A[i].property < p->property);
- while(p->property < a[j].property)
- j--;
+ do {
+ j -= 1;
+ } while(A[j].property > p->property);
if(i >= j)
break;
- const props_impl_t t = a[i];
- a[i] = a[j];
- a[j] = t;
+ const props_impl_t tmp = A[i];
+ A[i] = A[j];
+ A[j] = tmp;
}
- _impl_qsort(a, i);
- _impl_qsort(&a[i], n - i);
+ _props_qsort(A, j + 1);
+ _props_qsort(A + j + 1, n - j - 1);
}
static inline props_impl_t *
-_impl_bsearch(LV2_URID p, props_impl_t *a, unsigned n)
+_props_bsearch(props_t *props, LV2_URID property)
{
- unsigned start = 0;
- unsigned end = n;
+ props_impl_t *base = props->impls;
- while(start < end)
+ for(int N = props->nimpls, half; N > 1; N -= half)
{
- const unsigned mid = start + (end - start)/2;
- props_impl_t *dst = &a[mid];
-
- if(p < dst->property)
- end = mid;
- else if(p > dst->property)
- start = mid + 1;
- else
- return dst;
+ half = N/2;
+ props_impl_t *dst = &base[half];
+ base = (dst->property > property) ? base : dst;
}
- return NULL;
-}
-
-static inline props_impl_t *
-_props_impl_search(props_t *props, LV2_URID property)
-{
- return _impl_bsearch(property, props->impls, props->nimpls);
+ return (base->property == property) ? base : NULL;
}
static inline LV2_Atom_Forge_Ref
-_props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, props_impl_t *impl)
+_props_patch_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ props_impl_t *impl, int32_t sequence_num)
{
LV2_Atom_Forge_Frame obj_frame;
@@ -604,6 +292,14 @@ _props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, props_impl_t
ref = lv2_atom_forge_urid(forge, props->urid.subject);
}
+ if(sequence_num) // is optional
+ {
+ if(ref)
+ ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
+ if(ref)
+ ref = lv2_atom_forge_int(forge, sequence_num);
+ }
+
if(ref)
ref = lv2_atom_forge_key(forge, props->urid.patch_property);
if(ref)
@@ -612,7 +308,9 @@ _props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, props_impl_t
if(ref)
lv2_atom_forge_key(forge, props->urid.patch_value);
if(ref)
- ref = impl->type->get_cb(forge, impl->value);
+ ref = lv2_atom_forge_atom(forge, impl->value.size, impl->type);
+ if(ref)
+ ref = lv2_atom_forge_write(forge, impl->value.body, impl->value.size);
}
if(ref)
lv2_atom_forge_pop(forge, &obj_frame);
@@ -620,221 +318,188 @@ _props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, props_impl_t
return ref;
}
-static inline void
-_props_stash(props_t *props, props_impl_t *impl)
+static inline LV2_Atom_Forge_Ref
+_props_patch_error(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ int32_t sequence_num)
{
- if(_impl_try_lock(impl))
- {
- const uint32_t size = _impl_size_get(impl);
- memcpy(impl->stash, impl->value, size);
+ LV2_Atom_Forge_Frame obj_frame;
- _impl_unlock(impl);
- }
- else
+ LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
+
+ if(ref)
+ ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_error);
{
- impl->stashing = true;
- props->stashing= true;
+ if(ref)
+ ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
+ if(ref)
+ ref = lv2_atom_forge_int(forge, sequence_num);
}
-}
+ if(ref)
+ lv2_atom_forge_pop(forge, &obj_frame);
-static inline void
-_props_set(props_t *props, props_impl_t *impl, LV2_URID type, uint32_t sz, const void *value)
-{
- impl->type->set_cb(impl, impl->value, type, sz, value);
- _props_stash(props, impl);
+ return ref;
}
static inline LV2_Atom_Forge_Ref
-_props_reg(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, props_impl_t *impl)
+_props_patch_ack(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ int32_t sequence_num)
{
- const props_def_t *def = impl->def;
LV2_Atom_Forge_Frame obj_frame;
- LV2_Atom_Forge_Frame add_frame;
- LV2_Atom_Forge_Frame remove_frame;
LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
+
if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_patch);
+ ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_ack);
{
- if(props->urid.subject) // is optional
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_subject);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.subject);
- }
-
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_remove);
if(ref)
- ref = lv2_atom_forge_object(forge, &remove_frame, 0, 0);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, impl->access);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->property);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &remove_frame);
-
+ ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_add);
- if(ref)
- ref = lv2_atom_forge_object(forge, &add_frame, 0, 0);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, impl->access);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->property);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &add_frame);
+ ref = lv2_atom_forge_int(forge, sequence_num);
}
if(ref)
lv2_atom_forge_pop(forge, &obj_frame);
- if(ref)
- ref = lv2_atom_forge_frame_time(forge, frames);
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_patch);
+ return ref;
+}
+
+static inline void
+_props_impl_stash(props_t *props, props_impl_t *impl)
+{
+ if(_props_impl_try_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK))
{
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_subject);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->property);
+ impl->stashing = false;
+ impl->stash.size = impl->value.size;
+ memcpy(impl->stash.body, impl->value.body, impl->value.size);
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_remove);
- if(ref)
- ref = lv2_atom_forge_object(forge, &remove_frame, 0, 0);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_range);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+ _props_impl_unlock(impl, PROP_STATE_NONE);
+ }
+ else
+ {
+ impl->stashing = true; // try again later
+ props->stashing = true;
+ }
+}
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_label);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+static inline void
+_props_impl_restore(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ props_impl_t *impl, LV2_Atom_Forge_Ref *ref)
+{
+ if(_props_impl_try_lock(impl, PROP_STATE_RESTORE, PROP_STATE_LOCK))
+ {
+ impl->stashing = false; // makes no sense to stash a recently restored value
+ impl->value.size = impl->stash.size;
+ memcpy(impl->value.body, impl->stash.body, impl->stash.size);
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_comment);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+ _props_impl_unlock(impl, PROP_STATE_NONE);
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_minimum);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+ if(*ref)
+ *ref = _props_patch_set(props, forge, frames, impl, 0);
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_maximum);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+ const props_def_t *def = impl->def;
+ if(def->event_cb)
+ def->event_cb(props->data, 0, impl);
+ }
+}
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.units_unit);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
+static inline void
+_props_impl_set(props_t *props, props_impl_t *impl, LV2_URID type,
+ uint32_t size, const void *body)
+{
+ if( (impl->type == type)
+ && ( (impl->def->max_size == 0) || (size <= impl->def->max_size)) )
+ {
+ impl->value.size = size;
+ memcpy(impl->value.body, body, size);
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_scale_point);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.patch_wildcard);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &remove_frame);
+ _props_impl_stash(props, impl);
+ }
+}
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_add);
- if(ref)
- ref = lv2_atom_forge_object(forge, &add_frame, 0, 0);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_range);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->type->urid);
+static inline int
+_props_impl_init(props_t *props, props_impl_t *impl, const props_def_t *def,
+ void *value_base, void *stash_base, LV2_URID_Map *map)
+{
+ if(!def->property || !def->type)
+ return 0;
- if(def->label)
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_label);
- if(ref)
- ref = lv2_atom_forge_string(forge, def->label, strlen(def->label));
- }
+ const LV2_URID type = map->map(map->handle, def->type);
+ const LV2_URID property = map->map(map->handle, def->property);
+ const LV2_URID access = def->access
+ ? map->map(map->handle, def->access)
+ : map->map(map->handle, LV2_PATCH__writable);
- if(def->comment)
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_comment);
- if(ref)
- ref = lv2_atom_forge_string(forge, def->comment, strlen(def->comment));
- }
+ if(!type || !property || !access)
+ return 0;
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_minimum);
- if(ref)
- ref = impl->type->get_cb(forge, &def->minimum);
+ impl->property = property;
+ impl->access = access;
+ impl->def = def;
+ impl->value.body = value_base + def->offset;
+ impl->stash.body = stash_base + def->offset;
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_maximum);
- if(ref)
- ref = impl->type->get_cb(forge, &def->maximum);
+ uint32_t size;
+ if( (type == props->urid.atom_int)
+ || (type == props->urid.atom_float)
+ || (type == props->urid.atom_bool)
+ || (type == props->urid.atom_urid) )
+ {
+ size = 4;
+ }
+ else if((type == props->urid.atom_long)
+ || (type == props->urid.atom_double) )
+ {
+ size = 8;
+ }
+ else if(type == props->urid.atom_literal)
+ {
+ size = sizeof(LV2_Atom_Literal_Body);
+ }
+ else if(type == props->urid.atom_vector)
+ {
+ size = sizeof(LV2_Atom_Vector_Body);
+ }
+ else if(type == props->urid.atom_object)
+ {
+ size = sizeof(LV2_Atom_Object_Body);
+ }
+ else if(type == props->urid.atom_sequence)
+ {
+ size = sizeof(LV2_Atom_Sequence_Body);
+ }
+ else
+ {
+ size = 0; // assume everything else as having size 0
+ }
- if(props->urid.units_unit)
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.units_unit);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->unit);
- }
+ impl->type = type;
+ impl->value.size = size;
+ impl->stash.size = size;
- if(def->scale_points)
- {
- for(const props_scale_point_t *sp = def->scale_points; sp->label; sp++)
- {
- LV2_Atom_Forge_Frame scale_point_frame;
-
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.lv2_scale_point);
- if(ref)
- ref = lv2_atom_forge_object(forge, &scale_point_frame, 0, 0);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdfs_label);
- if(ref)
- ref = lv2_atom_forge_string(forge, sp->label, strlen(sp->label));
-
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.rdf_value);
- if(ref)
- ref = impl->type->get_cb(forge, &sp->value);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &scale_point_frame);
- }
- }
- }
- if(ref)
- lv2_atom_forge_pop(forge, &add_frame);
+ atomic_init(&impl->state, PROP_STATE_NONE);
+
+ // update maximal value size
+ const uint32_t max_size = def->max_size
+ ? def->max_size
+ : size;
+
+ if(max_size > props->max_size)
+ {
+ props->max_size = max_size;
}
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
- return ref;
+ return 1;
}
static inline int
-props_init(props_t *props, const size_t max_nimpls, const char *subject,
+props_init(props_t *props, const char *subject,
+ const props_def_t *defs, int nimpls,
+ void *value_base, void *stash_base,
LV2_URID_Map *map, void *data)
{
- if(!map)
+ if(!props || !defs || !value_base || !stash_base || !map)
return 0;
- props->nimpls = 0;
- props->max_nimpls = max_nimpls;
- props->map = map;
+ props->nimpls = nimpls;
props->data = data;
props->urid.subject = subject ? map->map(map->handle, subject) : 0;
@@ -852,20 +517,9 @@ props_init(props_t *props, const size_t max_nimpls, const char *subject,
props->urid.patch_value = map->map(map->handle, LV2_PATCH__value);
props->urid.patch_writable = map->map(map->handle, LV2_PATCH__writable);
props->urid.patch_readable = map->map(map->handle, LV2_PATCH__readable);
-
- props->urid.rdf_value = map->map(map->handle,
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#value");
-
- props->urid.rdfs_label = map->map(map->handle,
- "http://www.w3.org/2000/01/rdf-schema#label");
- props->urid.rdfs_range = map->map(map->handle,
- "http://www.w3.org/2000/01/rdf-schema#range");
- props->urid.rdfs_comment = map->map(map->handle,
- "http://www.w3.org/2000/01/rdf-schema#comment");
-
- props->urid.lv2_minimum = map->map(map->handle, LV2_CORE__minimum);
- props->urid.lv2_maximum = map->map(map->handle, LV2_CORE__maximum);
- props->urid.lv2_scale_point = map->map(map->handle, LV2_CORE__scalePoint);
+ props->urid.patch_sequence = map->map(map->handle, LV2_PATCH__sequenceNumber);
+ props->urid.patch_ack = map->map(map->handle, LV2_PATCH__Ack);
+ props->urid.patch_error = map->map(map->handle, LV2_PATCH__Error);
props->urid.atom_int = map->map(map->handle, LV2_ATOM__Int);
props->urid.atom_long = map->map(map->handle, LV2_ATOM__Long);
@@ -873,146 +527,42 @@ props_init(props_t *props, const size_t max_nimpls, const char *subject,
props->urid.atom_double = map->map(map->handle, LV2_ATOM__Double);
props->urid.atom_bool = map->map(map->handle, LV2_ATOM__Bool);
props->urid.atom_urid = map->map(map->handle, LV2_ATOM__URID);
- props->urid.atom_string = map->map(map->handle, LV2_ATOM__String);
props->urid.atom_path = map->map(map->handle, LV2_ATOM__Path);
- props->urid.atom_uri = map->map(map->handle, LV2_ATOM__URI);
- props->urid.atom_chunk = map->map(map->handle, LV2_ATOM__Chunk);
-
- props->urid.units_unit = map->map(map->handle, LV2_UNITS__unit);
-
- // Int
- unsigned ptr = 0;
- props->types[ptr].urid = props->urid.atom_int;
- props->types[ptr].size = sizeof(int32_t);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_int_get_cb;
- props->types[ptr].set_cb = _props_int_set_cb;
- ptr++;
-
- // Long
- props->types[ptr].urid = props->urid.atom_long;
- props->types[ptr].size = sizeof(int64_t);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_long_get_cb;
- props->types[ptr].set_cb = _props_long_set_cb;
- ptr++;
-
- // Float
- props->types[ptr].urid = props->urid.atom_float;
- props->types[ptr].size = sizeof(float);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_float_get_cb;
- props->types[ptr].set_cb = _props_float_set_cb;
- ptr++;
-
- // double
- props->types[ptr].urid = props->urid.atom_double;
- props->types[ptr].size = sizeof(double);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_double_get_cb;
- props->types[ptr].set_cb = _props_double_set_cb;
- ptr++;
-
- // Bool
- props->types[ptr].urid = props->urid.atom_bool;
- props->types[ptr].size = sizeof(int32_t);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_bool_get_cb;
- props->types[ptr].set_cb = _props_int_set_cb;
- ptr++;
-
- // URID
- props->types[ptr].urid = props->urid.atom_urid;
- props->types[ptr].size = sizeof(uint32_t);
- props->types[ptr].size_cb = NULL;
- props->types[ptr].get_cb = _props_urid_get_cb;
- props->types[ptr].set_cb = _props_urid_set_cb;
- ptr++;
-
- // String
- props->types[ptr].urid = props->urid.atom_string;
- props->types[ptr].size = 0;
- props->types[ptr].size_cb = _props_string_size_cb;
- props->types[ptr].get_cb = _props_string_get_cb;
- props->types[ptr].set_cb = _props_string_set_cb;
- ptr++;
-
- // Path
- props->types[ptr].urid = props->urid.atom_path;
- props->types[ptr].size = 0;
- props->types[ptr].size_cb = _props_string_size_cb;
- props->types[ptr].get_cb = _props_path_get_cb;
- props->types[ptr].set_cb = _props_string_set_cb;
- ptr++;
-
- // URI
- props->types[ptr].urid = props->urid.atom_uri;
- props->types[ptr].size = 0;
- props->types[ptr].size_cb = _props_string_size_cb;
- props->types[ptr].get_cb = _props_uri_get_cb;
- props->types[ptr].set_cb = _props_string_set_cb;
- ptr++;
-
- // URI
- props->types[ptr].urid = props->urid.atom_chunk;
- props->types[ptr].size = 0;
- props->types[ptr].size_cb = _props_chunk_size_cb;
- props->types[ptr].get_cb = _props_chunk_get_cb;
- props->types[ptr].set_cb = _props_chunk_set_cb;
- ptr++;
-
- assert(ptr == PROPS_TYPE_N);
- _type_qsort(props->types, PROPS_TYPE_N);
-
- return 1;
-}
-
-static inline LV2_URID
-props_register(props_t *props, const props_def_t *def, void *value, void *stash)
-{
- if(props->nimpls >= props->max_nimpls)
- return 0;
-
- if(!def || !def->property || !def->access || !def->type || !value || !stash)
- return 0;
-
- const LV2_URID type = props->map->map(props->map->handle, def->type);
- const props_type_t *props_type = _type_bsearch(type, props->types, PROPS_TYPE_N);
- const LV2_URID property = props->map->map(props->map->handle, def->property);
- const LV2_URID access = props->map->map(props->map->handle, def->access);
-
- if(!props_type || !property || !access)
- return 0;
+ props->urid.atom_literal = map->map(map->handle, LV2_ATOM__Literal);
+ props->urid.atom_vector = map->map(map->handle, LV2_ATOM__Vector);
+ props->urid.atom_object = map->map(map->handle, LV2_ATOM__Object);
+ props->urid.atom_sequence = map->map(map->handle, LV2_ATOM__Sequence);
- props_impl_t *impl = &props->impls[props->nimpls++];
+ atomic_init(&props->restoring, false);
- impl->props = props;
- impl->property = property;
- impl->access = access;
- impl->unit = def->unit ? props->map->map(props->map->handle, def->unit) : 0;
- impl->type = props_type;
- impl->def = def;
- impl->value = value;
- impl->stash = stash;
- atomic_flag_clear_explicit(&impl->lock, memory_order_relaxed);
+ int status = 1;
+ for(unsigned i = 0; i < props->nimpls; i++)
+ {
+ props_impl_t *impl = &props->impls[i];
- // update maximal value size
- if(props_type->size && (props_type->size > props->max_size) )
- props->max_size = props_type->size;
- else if(def->max_size && (def->max_size > props->max_size) )
- props->max_size = def->max_size;
-
- _impl_qsort(props->impls, props->nimpls);
+ status = status
+ && _props_impl_init(props, impl, &defs[i], value_base, stash_base, map);
+ }
- //TODO register?
+ _props_qsort(props->impls, props->nimpls);
- return property;
+ return status;
}
-static inline int
-props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref)
+static inline void
+props_idle(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ LV2_Atom_Forge_Ref *ref)
{
+ if(_props_restoring_get(props))
+ {
+ for(unsigned i = 0; i < props->nimpls; i++)
+ {
+ props_impl_t *impl = &props->impls[i];
+
+ _props_impl_restore(props, forge, frames, impl, ref);
+ }
+ }
+
if(props->stashing)
{
props->stashing = false;
@@ -1022,24 +572,30 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
props_impl_t *impl = &props->impls[i];
if(impl->stashing)
- {
- impl->stashing= false;
- _props_stash(props, impl);
- }
+ _props_impl_stash(props, impl);
}
}
+}
+static inline int
+props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref)
+{
if(!lv2_atom_forge_is_object_type(forge, obj->atom.type))
+ {
return 0;
+ }
if(obj->body.otype == props->urid.patch_get)
{
const LV2_Atom_URID *subject = NULL;
const LV2_Atom_URID *property = NULL;
+ const LV2_Atom_Int *sequence = NULL;
LV2_Atom_Object_Query q [] = {
{ props->urid.patch_subject, (const LV2_Atom **)&subject },
{ props->urid.patch_property, (const LV2_Atom **)&property },
+ { props->urid.patch_sequence, (const LV2_Atom **)&sequence },
LV2_ATOM_OBJECT_QUERY_END
};
lv2_atom_object_query(obj, q);
@@ -1052,6 +608,12 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
return 0;
}
+ int32_t sequence_num = 0;
+ if(sequence && (sequence->atom.type == props->urid.atom_int))
+ {
+ sequence_num = sequence->body;
+ }
+
if(!property)
{
for(unsigned i = 0; i < props->nimpls; i++)
@@ -1059,56 +621,50 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
props_impl_t *impl = &props->impls[i];
const props_def_t *def = impl->def;
- if(impl->def->mode == PROP_MODE_DYNAMIC)
- {
- if(*ref)
- *ref = _props_reg(props, forge, frames, impl);
- if(def->event_cb && (def->event_mask & PROP_EVENT_REGISTER) )
- def->event_cb(props->data, forge, frames, PROP_EVENT_REGISTER, impl);
- }
-
if(*ref)
- *ref = _props_get(props, forge, frames, impl);
- if(def->event_cb && (def->event_mask & PROP_EVENT_GET) )
- def->event_cb(props->data, forge, frames, PROP_EVENT_GET, impl);
+ *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
}
+
return 1;
}
else if(property->atom.type == props->urid.atom_urid)
{
- props_impl_t *impl = _props_impl_search(props, property->body);
+ props_impl_t *impl = _props_bsearch(props, property->body);
if(impl)
{
- *ref = _props_get(props, forge, frames, impl);
+ *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
const props_def_t *def = impl->def;
- if(def->event_cb && (def->event_mask & PROP_EVENT_GET) )
- def->event_cb(props->data, forge, frames, PROP_EVENT_GET, impl);
return 1;
}
+ else if(sequence_num)
+ {
+ *ref = _props_patch_error(props, forge, frames, sequence_num);
+ }
+ }
+ else if(sequence_num)
+ {
+ *ref = _props_patch_error(props, forge, frames, sequence_num);
}
}
else if(obj->body.otype == props->urid.patch_set)
{
const LV2_Atom_URID *subject = NULL;
const LV2_Atom_URID *property = NULL;
+ const LV2_Atom_Int *sequence = NULL;
const LV2_Atom *value = NULL;
LV2_Atom_Object_Query q [] = {
{ props->urid.patch_subject, (const LV2_Atom **)&subject },
{ props->urid.patch_property, (const LV2_Atom **)&property },
+ { props->urid.patch_sequence, (const LV2_Atom **)&sequence },
{ props->urid.patch_value, &value },
LV2_ATOM_OBJECT_QUERY_END
};
lv2_atom_object_query(obj, q);
- if(!property || (property->atom.type != props->urid.atom_urid) || !value)
- {
- return 0;
- }
-
// check for a matching optional subject
if( (subject && props->urid.subject)
&& ( (subject->atom.type != props->urid.atom_urid)
@@ -1117,35 +673,58 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
return 0;
}
- props_impl_t *impl = _props_impl_search(props, property->body);
+ int32_t sequence_num = 0;
+ if(sequence && (sequence->atom.type == props->urid.atom_int))
+ {
+ sequence_num = sequence->body;
+ }
+
+ if(!property || (property->atom.type != props->urid.atom_urid) || !value)
+ {
+ if(sequence_num)
+ {
+ *ref = _props_patch_error(props, forge, frames, sequence_num);
+ }
+
+ return 0;
+ }
+
+ props_impl_t *impl = _props_bsearch(props, property->body);
if(impl && (impl->access == props->urid.patch_writable) )
{
- _props_set(props, impl, value->type, value->size, LV2_ATOM_BODY_CONST(value));
+ _props_impl_set(props, impl, value->type, value->size,
+ LV2_ATOM_BODY_CONST(value));
const props_def_t *def = impl->def;
- if(def->event_cb && (def->event_mask & PROP_EVENT_SET) )
- def->event_cb(props->data, forge, frames, PROP_EVENT_SET, impl);
+ if(def->event_cb)
+ def->event_cb(props->data, frames, impl);
+
+ if(sequence_num)
+ {
+ *ref = _props_patch_ack(props, forge, frames, sequence_num);
+ }
return 1;
}
+ else if(sequence_num)
+ {
+ *ref = _props_patch_error(props, forge, frames, sequence_num);
+ }
}
else if(obj->body.otype == props->urid.patch_put)
{
const LV2_Atom_URID *subject = NULL;
+ const LV2_Atom_Int *sequence = NULL;
const LV2_Atom_Object *body = NULL;
LV2_Atom_Object_Query q [] = {
{ props->urid.patch_subject, (const LV2_Atom **)&subject },
+ { props->urid.patch_sequence, (const LV2_Atom **)&sequence},
{ props->urid.patch_body, (const LV2_Atom **)&body },
LV2_ATOM_OBJECT_QUERY_END
};
lv2_atom_object_query(obj, q);
- if(!body || !lv2_atom_forge_is_object_type(forge, body->atom.type))
- {
- return 0;
- }
-
// check for a matching optional subject
if( (subject && props->urid.subject)
&& ( (subject->atom.type != props->urid.atom_urid)
@@ -1154,21 +733,44 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
return 0;
}
+ int32_t sequence_num = 0;
+ if(sequence && (sequence->atom.type == props->urid.atom_int))
+ {
+ sequence_num = sequence->body;
+ }
+
+ if(!body || !lv2_atom_forge_is_object_type(forge, body->atom.type))
+ {
+ if(sequence_num)
+ {
+ *ref = _props_patch_error(props, forge, frames, sequence_num);
+ }
+
+ return 0;
+ }
+
LV2_ATOM_OBJECT_FOREACH(body, prop)
{
const LV2_URID property = prop->key;
const LV2_Atom *value = &prop->value;
- props_impl_t *impl = _props_impl_search(props, property);
+ props_impl_t *impl = _props_bsearch(props, property);
if(impl && (impl->access == props->urid.patch_writable) )
{
- _props_set(props, impl, value->type, value->size, LV2_ATOM_BODY_CONST(value));
+ _props_impl_set(props, impl, value->type, value->size,
+ LV2_ATOM_BODY_CONST(value));
const props_def_t *def = impl->def;
- if(def->event_cb && (def->event_mask & PROP_EVENT_SET) )
- def->event_cb(props->data, forge, frames, PROP_EVENT_SET, impl);
+ if(def->event_cb)
+ def->event_cb(props->data, frames, impl);
}
}
+
+ if(sequence_num)
+ {
+ *ref = _props_patch_ack(props, forge, frames, sequence_num);
+ }
+
return 1;
}
@@ -1176,30 +778,56 @@ props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
}
static inline void
-props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames, LV2_URID property,
- LV2_Atom_Forge_Ref *ref)
+props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
+ LV2_URID property, LV2_Atom_Forge_Ref *ref)
{
- props_impl_t *impl = _props_impl_search(props, property);
+ props_impl_t *impl = _props_bsearch(props, property);
if(impl)
{
- _props_stash(props, impl);
- if(*ref)
- *ref = _props_get(props, forge, frames, impl);
+ _props_impl_stash(props, impl);
+
+ if(*ref) //TODO use patch:sequenceNumber
+ *ref = _props_patch_set(props, forge, frames, impl, 0);
}
}
static inline void
props_stash(props_t *props, LV2_URID property)
{
- props_impl_t *impl = _props_impl_search(props, property);
+ props_impl_t *impl = _props_bsearch(props, property);
if(impl)
- _props_stash(props, impl);
+ _props_impl_stash(props, impl);
+}
+
+static inline LV2_URID
+props_map(props_t *props, const char *uri)
+{
+ for(unsigned i = 0; i < props->nimpls; i++)
+ {
+ props_impl_t *impl = &props->impls[i];
+
+ if(!strcmp(impl->def->property, uri))
+ return impl->property;
+ }
+
+ return 0;
+}
+
+static inline const char *
+props_unmap(props_t *props, LV2_URID property)
+{
+ props_impl_t *impl = _props_bsearch(props, property);
+
+ if(impl)
+ return impl->def->property;
+
+ return NULL;
}
static inline LV2_State_Status
-props_save(props_t *props, LV2_Atom_Forge *forge, LV2_State_Store_Function store,
+props_save(props_t *props, LV2_State_Store_Function store,
LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features)
{
const LV2_State_Map_Path *map_path = NULL;
@@ -1216,8 +844,8 @@ props_save(props_t *props, LV2_Atom_Forge *forge, LV2_State_Store_Function store
}
}
- void *value = malloc(props->max_size); // create memory to store widest value
- if(value)
+ void *body = malloc(props->max_size); // create memory to store widest value
+ if(body)
{
for(unsigned i = 0; i < props->nimpls; i++)
{
@@ -1226,44 +854,42 @@ props_save(props_t *props, LV2_Atom_Forge *forge, LV2_State_Store_Function store
if(impl->access == props->urid.patch_readable)
continue; // skip read-only, as it makes no sense to restore them
- // create lockfree copy of value, store() may well be blocking
- _impl_spin_lock(impl);
+ _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
- const uint32_t size = _impl_size_get(impl);
- memcpy(value, impl->stash, size);
+ // create temporary copy of value, store() may well be blocking
+ const uint32_t size = impl->stash.size;
+ memcpy(body, impl->stash.body, size);
- _impl_unlock(impl);
+ _props_impl_unlock(impl, PROP_STATE_NONE);
- if( map_path && (impl->type->urid == forge->Path) )
+ if( map_path && (impl->type == props->urid.atom_path) )
{
- const char *path = strstr(value, "file://")
- ? value + 7 // skip "file://"
- : value;
+ const char *path = strstr(body, "file://")
+ ? body + 7 // skip "file://"
+ : body;
char *abstract = map_path->abstract_path(map_path->handle, path);
- if(abstract && strcmp(abstract, path))
+ if(abstract)
{
- store(state, impl->property, abstract, strlen(abstract) + 1, impl->type->urid, flags);
+ const uint32_t sz = strlen(abstract) + 1;
+ store(state, impl->property, abstract, sz, impl->type, flags);
+
free(abstract);
}
}
else // !Path
{
- store(state, impl->property, value, size, impl->type->urid, flags);
+ store(state, impl->property, body, size, impl->type, flags);
}
-
- const props_def_t *def = impl->def;
- if(def->event_cb && (def->event_mask & PROP_EVENT_SAVE) )
- def->event_cb(props->data, forge, 0, PROP_EVENT_SAVE, impl);
}
- free(value);
+ free(body);
}
return LV2_STATE_SUCCESS;
}
static inline LV2_State_Status
-props_restore(props_t *props, LV2_Atom_Forge *forge, LV2_State_Retrieve_Function retrieve,
+props_restore(props_t *props, LV2_State_Retrieve_Function retrieve,
LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features)
{
const LV2_State_Map_Path *map_path = NULL;
@@ -1284,40 +910,46 @@ props_restore(props_t *props, LV2_Atom_Forge *forge, LV2_State_Retrieve_Function
size_t size;
uint32_t type;
uint32_t _flags;
- const void *value = retrieve(state, impl->property, &size, &type, &_flags);
+ const void *body = retrieve(state, impl->property, &size, &type, &_flags);
- if(value)
+ if( body
+ && (type == impl->type)
+ && ( (impl->def->max_size == 0) || (size <= impl->def->max_size) ) )
{
- if( map_path && (impl->type->urid == forge->Path) )
+ if(map_path && (type == props->urid.atom_path) )
{
- char *absolute = map_path->absolute_path(map_path->handle, value);
+ char *absolute = map_path->absolute_path(map_path->handle, body);
if(absolute)
{
- _props_set(props, impl, type, strlen(absolute) + 1, absolute);
+ const uint32_t sz = strlen(absolute) + 1;
+
+ _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
+
+ impl->stash.size = sz;
+ memcpy(impl->stash.body, absolute, sz);
+
+ _props_impl_unlock(impl, PROP_STATE_RESTORE);
+
free(absolute);
}
}
else // !Path
{
- _props_set(props, impl, type, size, value);
- }
+ _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
- const props_def_t *def = impl->def;
- if(def->event_cb && (def->event_mask & PROP_EVENT_RESTORE) )
- def->event_cb(props->data, forge, 0, PROP_EVENT_RESTORE, impl);
- }
- else
- {
- fprintf(stderr, "props_restore: no property '%s'.\n", impl->def->property);
+ impl->stash.size = size;
+ memcpy(impl->stash.body, body, size);
+
+ _props_impl_unlock(impl, PROP_STATE_RESTORE);
+ }
}
}
+ _props_restoring_set(props);
+
return LV2_STATE_SUCCESS;
}
-// undefinitions
-#undef PROPS_TYPE_N
-
#ifdef __cplusplus
}
#endif
diff --git a/test/props.c b/test/props.c
index 516d48c..edeac6a 100644
--- a/test/props.c
+++ b/test/props.c
@@ -20,28 +20,18 @@
#include <props.h>
#include <lv2/lv2plug.in/ns/ext/log/log.h>
+#include <lv2/lv2plug.in/ns/ext/log/logger.h>
#define PROPS_PREFIX "http://open-music-kontrollers.ch/lv2/props#"
#define PROPS_TEST_URI PROPS_PREFIX"test"
-#define MAX_NPROPS 33
+#define MAX_NPROPS 7
#define MAX_STRLEN 256
-typedef struct _plugstate0_t plugstate0_t;
-typedef struct _plugstate1_t plugstate1_t;
+typedef struct _plugstate_t plugstate_t;
typedef struct _plughandle_t plughandle_t;
-struct _plugstate0_t {
- int32_t val1;
- int64_t val2;
- float val3;
- double val4;
- int32_t val5;
- int32_t val6;
- char val7 [MAX_STRLEN];
-};
-
-struct _plugstate1_t {
+struct _plugstate_t {
int32_t val1;
int64_t val2;
float val3;
@@ -54,344 +44,118 @@ struct _plugstate1_t {
struct _plughandle_t {
LV2_URID_Map *map;
LV2_Log_Log *log;
+ LV2_Log_Logger logger;
LV2_Atom_Forge forge;
LV2_Atom_Forge_Ref ref;
- LV2_URID log_trace;
- LV2_URID log_note;
-
PROPS_T(props, MAX_NPROPS);
-
- plugstate0_t dyn;
- plugstate0_t _dyn;
-
- plugstate1_t stat;
- plugstate1_t _stat;
+ plugstate_t state;
+ plugstate_t stash;
struct {
- LV2_URID stat2;
- LV2_URID stat4;
- LV2_URID dyn2;
- LV2_URID dyn4;
+ LV2_URID val2;
+ LV2_URID val4;
} urid;
const LV2_Atom_Sequence *event_in;
LV2_Atom_Sequence *event_out;
};
-static int
-_log_vprintf(plughandle_t *handle, LV2_URID type, const char *fmt, va_list args)
-{
- return handle->log->vprintf(handle->log->handle, type, fmt, args);
-}
-
-// non-rt || rt with LV2_LOG__Trace
-static int
-_log_printf(plughandle_t *handle, LV2_URID type, const char *fmt, ...)
-{
- va_list args;
- int ret;
-
- va_start (args, fmt);
- ret = _log_vprintf(handle, type, fmt, args);
- va_end(args);
-
- return ret;
-}
-
static void
-_intercept(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
+_intercept(void *data, int64_t frames, props_impl_t *impl)
{
plughandle_t *handle = data;
- switch(event)
- {
- case PROP_EVENT_GET:
- {
- _log_printf(handle, handle->log_trace, "GET : %s", impl->def->label);
- break;
- }
- case PROP_EVENT_SET:
- {
- _log_printf(handle, handle->log_trace, "SET : %s", impl->def->label);
- break;
- }
- case PROP_EVENT_REGISTER:
- {
- _log_printf(handle, handle->log_trace, "REGISTER: %s", impl->def->label);
- break;
- }
- case PROP_EVENT_SAVE:
- {
- _log_printf(handle, handle->log_note, "SAVE : %s", impl->def->label);
- break;
- }
- case PROP_EVENT_RESTORE:
- {
- _log_printf(handle, handle->log_note, "RESTORE : %s", impl->def->label);
- break;
- }
- }
+ lv2_log_trace(&handle->logger, "SET : %s\n", impl->def->property);
}
static void
-_intercept_dyn1(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
+_intercept_stat1(void *data, int64_t frames, props_impl_t *impl)
{
plughandle_t *handle = data;
- _intercept(data, forge, frames, event, impl);
+ _intercept(data, frames, impl);
- if(event & PROP_EVENT_WRITE)
- {
- handle->dyn.val2 = handle->dyn.val1 * 2;
+ handle->state.val2 = handle->state.val1 * 2;
- props_set(&handle->props, forge, frames, handle->urid.dyn2, &handle->ref);
- }
+ props_set(&handle->props, &handle->forge, frames, handle->urid.val2, &handle->ref);
}
static void
-_intercept_dyn3(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
+_intercept_stat3(void *data, int64_t frames, props_impl_t *impl)
{
plughandle_t *handle = data;
- _intercept(data, forge, frames, event, impl);
+ _intercept(data, frames, impl);
- if(event & PROP_EVENT_WRITE)
- {
- handle->dyn.val4 = handle->dyn.val3 * 2;
+ handle->state.val4 = handle->state.val3 * 2;
- props_set(&handle->props, forge, frames, handle->urid.dyn4, &handle->ref);
- }
+ props_set(&handle->props, &handle->forge, frames, handle->urid.val4, &handle->ref);
}
static void
-_intercept_stat1(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
+_intercept_stat6(void *data, int64_t frames, props_impl_t *impl)
{
plughandle_t *handle = data;
- _intercept(data, forge, frames, event, impl);
+ _intercept(data, frames, impl);
- if(event & PROP_EVENT_WRITE)
- {
- handle->stat.val2 = handle->stat.val1 * 2;
-
- props_set(&handle->props, forge, frames, handle->urid.stat2, &handle->ref);
- }
+ const char *path = strstr(handle->state.val6, "file://")
+ ? handle->state.val6 + 7 // skip "file://"
+ : handle->state.val6;
+ FILE *f = fopen(path, "wb"); // create empty file
+ if(f)
+ fclose(f);
}
-static void
-_intercept_stat3(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- _intercept(data, forge, frames, event, impl);
-
- if(event & PROP_EVENT_WRITE)
+static const props_def_t defs [MAX_NPROPS] = {
{
- handle->stat.val4 = handle->stat.val3 * 2;
-
- props_set(&handle->props, forge, frames, handle->urid.stat4, &handle->ref);
- }
-}
-
-static void
-_intercept_stat6(void *data, LV2_Atom_Forge *forge, int64_t frames,
- props_event_t event, props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- _intercept(data, forge, frames, event, impl);
-
- if(event & PROP_EVENT_WRITE)
+ .property = PROPS_PREFIX"statInt",
+ .offset = offsetof(plugstate_t, val1),
+ .type = LV2_ATOM__Int,
+ .event_cb = _intercept_stat1,
+ },
+ {
+ .property = PROPS_PREFIX"statLong",
+ .access = LV2_PATCH__readable,
+ .offset = offsetof(plugstate_t, val2),
+ .type = LV2_ATOM__Long,
+ .event_cb = _intercept,
+ },
+ {
+ .property = PROPS_PREFIX"statFloat",
+ .offset = offsetof(plugstate_t, val3),
+ .type = LV2_ATOM__Float,
+ .event_cb = _intercept_stat3,
+ },
+ {
+ .property = PROPS_PREFIX"statDouble",
+ .access = LV2_PATCH__readable,
+ .offset = offsetof(plugstate_t, val4),
+ .type = LV2_ATOM__Double,
+ .event_cb = _intercept,
+ },
{
- const char *path = strstr(handle->stat.val6, "file://")
- ? handle->stat.val6 + 7 // skip "file://"
- : handle->stat.val6;
- FILE *f = fopen(path, "wb"); // create empty file
- if(f)
- fclose(f);
+ .property = PROPS_PREFIX"statString",
+ .offset = offsetof(plugstate_t, val5),
+ .type = LV2_ATOM__String,
+ .event_cb = _intercept,
+ .max_size = MAX_STRLEN // strlen
+ },
+ {
+ .property = PROPS_PREFIX"statPath",
+ .offset = offsetof(plugstate_t, val6),
+ .type = LV2_ATOM__Path,
+ .event_cb = _intercept_stat6,
+ .max_size = MAX_STRLEN // strlen
+ },
+ {
+ .property = PROPS_PREFIX"statChunk",
+ .offset = offsetof(plugstate_t, val7),
+ .type = LV2_ATOM__Chunk,
+ .event_cb = _intercept,
+ .max_size = MAX_STRLEN // strlen
}
-}
-
-static const props_def_t dyn1 = {
- .label = "Int",
- .comment = "This is a 32-bit integer",
- .property = PROPS_PREFIX"Int",
- .access = LV2_PATCH__writable,
- .unit = LV2_UNITS__hz,
- .type = LV2_ATOM__Int,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept_dyn1,
- .minimum.i = 0,
- .maximum.i = 10
-};
-
-static const props_def_t dyn2 = {
- .label = "Long",
- .comment = "This is a 64-bit integer",
- .property = PROPS_PREFIX"Long",
- .access = LV2_PATCH__readable,
- .unit = LV2_UNITS__khz,
- .type = LV2_ATOM__Long,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .minimum.h = 0,
- .maximum.h = 20
-};
-
-static const props_def_t dyn3 = {
- .label = "Float",
- .comment = "This is a 32-bit floating point",
- .property = PROPS_PREFIX"Float",
- .access = LV2_PATCH__writable,
- .unit = LV2_UNITS__mhz,
- .type = LV2_ATOM__Float,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept_dyn3,
- .minimum.f = -0.5f,
- .maximum.f = 0.5f
-};
-
-static const props_def_t dyn4 = {
- .label = "Double",
- .comment = "This is a 64-bit floating point",
- .property = PROPS_PREFIX"Double",
- .access = LV2_PATCH__readable,
- .unit = LV2_UNITS__db,
- .type = LV2_ATOM__Double,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .minimum.d = -1.0,
- .maximum.d = 1.0
-};
-
-static const props_scale_point_t scale_points5 [] = {
- {.label = "One", .value.i = 0},
- {.label = "Two", .value.i = 1},
- {.label = "Three", .value.i = 2},
- {.label = "Four", .value.i = 3},
- {.label = NULL } // sentinel
-};
-
-static const props_def_t dyn5 = {
- .label = "scaleInt",
- .comment = "This is a 32-bit integer enumeration",
- .property = PROPS_PREFIX"scaleInt",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Int,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .minimum.i = 0,
- .maximum.i = 3,
- .scale_points = scale_points5
-};
-
-static const props_def_t dyn6 = {
- .label = "Bool",
- .comment = "This is a boolean",
- .property = PROPS_PREFIX"Bool",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Bool,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .minimum.d = 0,
- .maximum.d = 1
-};
-
-static const props_def_t dyn7 = {
- .label = "String",
- .comment = "This is a string",
- .property = PROPS_PREFIX"String",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__String,
- .mode = PROP_MODE_DYNAMIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .max_size = MAX_STRLEN // strlen
-};
-
-static const props_def_t stat1 = {
- .label = "statInt",
- .property = PROPS_PREFIX"statInt",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Int,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept_stat1,
-};
-
-static const props_def_t stat2 = {
- .label = "statLong",
- .property = PROPS_PREFIX"statLong",
- .access = LV2_PATCH__readable,
- .type = LV2_ATOM__Long,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
-};
-
-static const props_def_t stat3 = {
- .label = "statFloat",
- .property = PROPS_PREFIX"statFloat",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Float,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept_stat3,
-};
-
-static const props_def_t stat4 = {
- .label = "statDouble",
- .property = PROPS_PREFIX"statDouble",
- .access = LV2_PATCH__readable,
- .type = LV2_ATOM__Double,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
-};
-
-static const props_def_t stat5 = {
- .label = "statString",
- .property = PROPS_PREFIX"statString",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__String,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .max_size = MAX_STRLEN // strlen
-};
-
-static const props_def_t stat6 = {
- .label = "statPath",
- .property = PROPS_PREFIX"statPath",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Path,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept_stat6,
- .max_size = MAX_STRLEN // strlen
-};
-
-static const props_def_t stat7 = {
- .label = "statChunk",
- .property = PROPS_PREFIX"statChunk",
- .access = LV2_PATCH__writable,
- .type = LV2_ATOM__Chunk,
- .mode = PROP_MODE_STATIC,
- .event_mask = PROP_EVENT_ALL,
- .event_cb = _intercept,
- .max_size = MAX_STRLEN // strlen
};
static LV2_Handle
@@ -425,47 +189,21 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
return NULL;
}
- handle->log_trace = handle->map->map(handle->map->handle, LV2_LOG__Trace);
- handle->log_note = handle->map->map(handle->map->handle, LV2_LOG__Note);
-
+ lv2_log_logger_init(&handle->logger, handle->map, handle->log);
lv2_atom_forge_init(&handle->forge, handle->map);
- if(!props_init(&handle->props, MAX_NPROPS, descriptor->URI, handle->map, handle))
- {
- fprintf(stderr, "failed to initialize property structure\n");
- free(handle);
- return NULL;
- }
- plugstate0_t *dyn = &handle->dyn;
- plugstate0_t *_dyn = &handle->_dyn;
- plugstate1_t *stat = &handle->stat;
- plugstate1_t *_stat = &handle->_stat;
-
- if( !props_register(&handle->props, &dyn1, &dyn->val1, &_dyn->val1)
- || !(handle->urid.dyn2 =
- props_register(&handle->props, &dyn2, &dyn->val2, &_dyn->val2))
- || !props_register(&handle->props, &dyn3, &dyn->val3, &_dyn->val3)
- || !(handle->urid.dyn4 =
- props_register(&handle->props, &dyn4, &dyn->val4, &_dyn->val4))
- || !props_register(&handle->props, &dyn5, &dyn->val5, &_dyn->val5)
- || !props_register(&handle->props, &dyn6, &dyn->val6, &_dyn->val6)
- || !props_register(&handle->props, &dyn7, &dyn->val7, &_dyn->val7)
-
- || !props_register(&handle->props, &stat1, &stat->val1, &_stat->val1)
- || !(handle->urid.stat2 =
- props_register(&handle->props, &stat2, &stat->val2, &_stat->val2))
- || !props_register(&handle->props, &stat3, &stat->val3, &_stat->val3)
- || !(handle->urid.stat4 =
- props_register(&handle->props, &stat4, &stat->val4, &_stat->val4))
- || !props_register(&handle->props, &stat5, &stat->val5, &_stat->val5)
- || !props_register(&handle->props, &stat6, &stat->val6, &_stat->val6)
- || !props_register(&handle->props, &stat7, &stat->val7, &_stat->val7) )
+ if(!props_init(&handle->props, descriptor->URI,
+ defs, MAX_NPROPS, &handle->state, &handle->stash,
+ handle->map, handle))
{
- _log_printf(handle, handle->log_trace, "ERR : registering");
+ lv2_log_error(&handle->logger, "failed to initialize property structure\n");
free(handle);
return NULL;
}
+ handle->urid.val2 = props_map(&handle->props, PROPS_PREFIX"statLong");
+ handle->urid.val4 = props_map(&handle->props, PROPS_PREFIX"statDouble");
+
return handle;
}
@@ -497,13 +235,16 @@ run(LV2_Handle instance, uint32_t nsamples)
lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->event_out, capacity);
handle->ref = lv2_atom_forge_sequence_head(&handle->forge, &frame, 0);
+ props_idle(&handle->props, &handle->forge, 0, &handle->ref);
+
LV2_ATOM_SEQUENCE_FOREACH(handle->event_in, ev)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
if(handle->ref)
- props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref); //TODO handle return
+ props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref);
}
+
if(handle->ref)
lv2_atom_forge_pop(&handle->forge, &frame);
else
@@ -525,7 +266,7 @@ _state_save(LV2_Handle instance, LV2_State_Store_Function store,
{
plughandle_t *handle = (plughandle_t *)instance;
- return props_save(&handle->props, &handle->forge, store, state, flags, features);
+ return props_save(&handle->props, store, state, flags, features);
}
static LV2_State_Status
@@ -535,7 +276,7 @@ _state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
{
plughandle_t *handle = (plughandle_t *)instance;
- return props_restore(&handle->props, &handle->forge, retrieve, state, flags, features);
+ return props_restore(&handle->props, retrieve, state, flags, features);
}
LV2_State_Interface state_iface = {
diff --git a/test/props.ttl b/test/props.ttl
index 17a8041..0ce45d6 100644
--- a/test/props.ttl
+++ b/test/props.ttl
@@ -106,9 +106,9 @@ props:test
doap:name "Props Test" ;
doap:license lic:Artistic-2.0 ;
lv2:project proj:props ;
- lv2:extensionData state:interface ;
lv2:requiredFeature urid:map, log:log, state:loadDefaultState ;
- lv2:optionalFeature lv2:isLive, lv2:hardRTCapable ;
+ lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, state:threadSafeRestore ;
+ lv2:extensionData state:interface ;
lv2:port [
# sink event port
@@ -147,6 +147,6 @@ props:test
props:statInt 4 ;
props:statFloat "0.4"^^xsd:float ;
props:statString "Hello world" ;
- props:statPath <manifest.ttl> ;
- props:statChunk "Q"^^xsd:base64Binary ;
+ props:statPath <props.ttl> ;
+ props:statChunk "AQIDBAUGBw=="^^xsd:base64Binary ;
] .