aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2016-06-07 16:55:05 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2016-06-07 16:55:05 +0200
commit1e7d3c4518794a14c934bf783a6c6639f4d3095a (patch)
treee7f63d0249a2573a814bbba9768431042451146c
parentf42d2337cfba49be6868905d57ad28af4a6a2053 (diff)
downloadsherlock.lv2-1e7d3c4518794a14c934bf783a6c6639f4d3095a.tar.xz
implement parameters and state.
-rw-r--r--CMakeLists.txt1
-rw-r--r--VERSION2
-rw-r--r--atom_inspector.c97
-rw-r--r--atom_inspector_eo.c231
-rw-r--r--midi_inspector.c100
-rw-r--r--midi_inspector_eo.c224
-rw-r--r--osc_inspector.c98
-rw-r--r--osc_inspector_eo.c226
-rw-r--r--sherlock.h41
-rw-r--r--sherlock.ttl98
10 files changed, 882 insertions, 236 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 47c5a40..ead9152 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,7 @@ include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/libosc)
include_directories(${PROJECT_SOURCE_DIR}/osc.lv2)
include_directories(${PROJECT_SOURCE_DIR}/sandbox_ui.lv2)
+include_directories(${PROJECT_SOURCE_DIR}/props.lv2)
include_directories(${PROJECT_SOURCE_DIR}/symap)
set(CMAKE_C_FLAGS "-std=gnu11 -Wextra -Wno-unused-parameter -ffast-math -fvisibility=hidden ${CMAKE_C_FLAGS}")
diff --git a/VERSION b/VERSION
index b64934d..b7303ca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.9.65
+0.9.131
diff --git a/atom_inspector.c b/atom_inspector.c
index 87de9d9..86d948f 100644
--- a/atom_inspector.c
+++ b/atom_inspector.c
@@ -33,6 +33,10 @@ struct _handle_t {
LV2_URID time_frame;
int64_t frame;
+
+ PROPS_T(props, MAX_NPROPS);
+ state_t state;
+ state_t stash;
};
static LV2_Handle
@@ -60,6 +64,22 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
lv2_atom_forge_init(&handle->forge, handle->map);
+ if(!props_init(&handle->props, MAX_NPROPS, descriptor->URI, handle->map, handle))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(handle);
+ return NULL;
+ }
+
+ if( !props_register(&handle->props, &stat_count, &handle->state.count, &handle->stash.count)
+ || !props_register(&handle->props, &stat_overwrite, &handle->state.overwrite, &handle->stash.overwrite)
+ || !props_register(&handle->props, &stat_block, &handle->state.block, &handle->stash.block)
+ || !props_register(&handle->props, &stat_follow, &handle->state.follow, &handle->stash.follow) )
+ {
+ free(handle);
+ return NULL;
+ }
+
return handle;
}
@@ -93,30 +113,40 @@ run(LV2_Handle instance, uint32_t nsamples)
LV2_Atom_Forge_Frame frame;
LV2_Atom_Forge_Ref ref;
+ // size of input sequence
+ const size_t size = lv2_atom_total_size(&handle->control_in->atom);
+
+ capacity = handle->control_out->atom.size;
+ lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
+ ref = lv2_atom_forge_sequence_head(forge, &frame, 0);
+
LV2_ATOM_SEQUENCE_FOREACH(handle->control_in, ev)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
+ const int64_t frames = ev->time.frames;
+
+ // copy all events to through port
+ if(ref)
+ ref = lv2_atom_forge_frame_time(forge, frames);
+ if(ref)
+ ref = lv2_atom_forge_raw(forge, &obj->atom, lv2_atom_total_size(&obj->atom));
+ if(ref)
+ lv2_atom_forge_pad(forge, obj->atom.size);
- if(lv2_atom_forge_is_object_type(forge, obj->atom.type))
+ if( !props_advance(&handle->props, forge, frames, obj, &ref)
+ && lv2_atom_forge_is_object_type(forge, obj->atom.type)
+ && (obj->body.otype == handle->time_position) )
{
- if(obj->body.otype == handle->time_position)
- {
- const LV2_Atom_Long *time_frame = NULL;
- lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
- if(time_frame)
- handle->frame = time_frame->body - ev->time.frames;
- }
+ const LV2_Atom_Long *time_frame = NULL;
+ lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
+ if(time_frame)
+ handle->frame = time_frame->body - frames;
}
}
- // size of input sequence
- size_t size = sizeof(LV2_Atom) + handle->control_in->atom.size;
-
- // copy whole input sequence to through port
- capacity = handle->control_out->atom.size;
- lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
- ref = lv2_atom_forge_raw(forge, handle->control_in, size);
- if(!ref)
+ if(ref)
+ lv2_atom_forge_pop(forge, &frame);
+ else
lv2_atom_sequence_clear(handle->control_out);
// forge whole sequence as single event
@@ -160,6 +190,39 @@ cleanup(LV2_Handle instance)
free(handle);
}
+static LV2_State_Status
+_state_save(LV2_Handle instance, LV2_State_Store_Function store,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_save(&handle->props, &handle->forge, store, state, flags, features);
+}
+
+static LV2_State_Status
+_state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_restore(&handle->props, &handle->forge, retrieve, state, flags, features);
+}
+
+static const LV2_State_Interface state_iface = {
+ .save = _state_save,
+ .restore = _state_restore
+};
+
+static const void *
+extension_data(const char *uri)
+{
+ if(!strcmp(uri, LV2_STATE__interface))
+ return &state_iface;
+ return NULL;
+}
+
const LV2_Descriptor atom_inspector = {
.URI = SHERLOCK_ATOM_INSPECTOR_URI,
.instantiate = instantiate,
@@ -168,5 +231,5 @@ const LV2_Descriptor atom_inspector = {
.run = run,
.deactivate = NULL,
.cleanup = cleanup,
- .extension_data = NULL
+ .extension_data = extension_data
};
diff --git a/atom_inspector_eo.c b/atom_inspector_eo.c
index 89349eb..2033234 100644
--- a/atom_inspector_eo.c
+++ b/atom_inspector_eo.c
@@ -43,9 +43,7 @@ struct _UI {
LV2_URID_Map *map;
LV2_URID_Unmap *unmap;
- struct {
- LV2_URID event_transfer;
- } uris;
+ LV2_URID event_transfer;
LV2_Atom_Forge forge;
@@ -71,7 +69,15 @@ struct _UI {
const char *base_uri;
char *chunk;
- int count_max;
+
+ PROPS_T(props, MAX_NPROPS);
+ struct {
+ LV2_URID overwrite;
+ LV2_URID block;
+ LV2_URID follow;
+ } urid;
+ state_t state;
+ state_t stash;
};
#define CODE_PRE "<style=shadow,bottom>"
@@ -359,7 +365,7 @@ _clear_update(UI *ui, int count)
return;
char *buf = ui->string_buf;
- sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->count_max);
+ sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->state.count);
elm_object_text_set(ui->clear, buf);
}
@@ -407,6 +413,70 @@ _content_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
evas_object_del(ui->widget);
}
+static inline void
+_discover(UI *ui)
+{
+ union {
+ LV2_Atom atom;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+ LV2_Atom_Forge_Frame frame;
+
+ if(lv2_atom_forge_object(&ui->forge, &frame, 0, ui->props.urid.patch_get))
+ {
+ lv2_atom_forge_pop(&ui->forge, &frame);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.atom),
+ ui->event_transfer, &buf.atom);
+ }
+}
+
+static inline void
+_check_changed(UI *ui, LV2_URID property)
+{
+ union {
+ LV2_Atom_Event ev;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+
+ LV2_Atom_Forge_Ref ref = 1;
+ props_set(&ui->props, &ui->forge, 0, property, &ref);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.ev.body),
+ ui->event_transfer, &buf.ev.body);
+}
+
+static void
+_autoclear_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.overwrite = elm_check_state_get(ui->autoclear) ? 1 : 0;
+ _check_changed(ui, ui->urid.overwrite);
+}
+
+static void
+_autoblock_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.block = elm_check_state_get(ui->autoblock) ? 1 : 0;
+ _check_changed(ui, ui->urid.block);
+}
+
+static void
+_autofollow_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.follow = elm_check_state_get(ui->autofollow) ? 1 : 0;
+ _check_changed(ui, ui->urid.follow);
+}
+
static Evas_Object *
_content_get(UI *ui, Evas_Object *parent)
{
@@ -477,6 +547,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoclear)
{
elm_object_text_set(ui->autoclear, "overwrite");
+ evas_object_smart_callback_add(ui->autoclear, "changed", _autoclear_changed, ui);
evas_object_size_hint_weight_set(ui->autoclear, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoclear, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoclear);
@@ -487,6 +558,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoblock)
{
elm_object_text_set(ui->autoblock, "block");
+ evas_object_smart_callback_add(ui->autoblock, "changed", _autoblock_changed, ui);
evas_object_size_hint_weight_set(ui->autoblock, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoblock, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoblock);
@@ -497,6 +569,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autofollow)
{
elm_object_text_set(ui->autofollow, "follow");
+ evas_object_smart_callback_add(ui->autofollow, "changed", _autofollow_changed, ui);
evas_object_size_hint_weight_set(ui->autofollow, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autofollow, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autofollow);
@@ -644,7 +717,7 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
sprintf(ui->string_buf, "%s/omk_logo_256x256.png", bundle_path);
ui->logo_path = strdup(ui->string_buf);
- ui->uris.event_transfer = ui->map->map(ui->map->handle, LV2_ATOM__eventTransfer);
+ ui->event_transfer = ui->map->map(ui->map->handle, LV2_ATOM__eventTransfer);
ui->urids = eina_hash_int32_new(_hash_del);
@@ -674,7 +747,23 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
}
*(Evas_Object **)widget = ui->widget;
- ui->count_max = 2048;
+ if(!props_init(&ui->props, MAX_NPROPS, plugin_uri, ui->map, ui))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(ui);
+ return NULL;
+ }
+
+ if( !props_register(&ui->props, &stat_count, &ui->state.count, &ui->stash.count)
+ || !(ui->urid.overwrite = props_register(&ui->props, &stat_overwrite, &ui->state.overwrite, &ui->stash.overwrite))
+ || !(ui->urid.block = props_register(&ui->props, &stat_block, &ui->state.block, &ui->stash.block))
+ || !(ui->urid.follow = props_register(&ui->props, &stat_follow, &ui->state.follow, &ui->stash.follow)) )
+ {
+ free(ui);
+ return NULL;
+ }
+
+ _discover(ui);
return ui;
}
@@ -707,74 +796,96 @@ port_event(LV2UI_Handle handle, uint32_t i, uint32_t size, uint32_t urid,
const void *buf)
{
UI *ui = handle;
-
- if( (i == 2) && (urid == ui->uris.event_transfer) && ui->list)
+
+ if(urid != ui->event_transfer)
+ return;
+
+ switch(i)
{
- const LV2_Atom_Tuple *tup = buf;
- const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
- const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
- const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
- int n = elm_genlist_items_count(ui->list);
-
- Elm_Object_Item *itm = NULL;
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
+ case 0:
+ case 1:
{
- position_t *pos = malloc(sizeof(position_t));
- if(!pos)
- return;
-
- pos->offset = offset->body;
- pos->nsamples = nsamples->body;
+ LV2_Atom_Forge_Ref ref = 1;
+ if(props_advance(&ui->props, &ui->forge, 0, (const LV2_Atom_Object *)buf, &ref))
+ {
+ elm_check_state_set(ui->autoclear, ui->state.overwrite);
+ elm_check_state_set(ui->autoblock, ui->state.block);
+ elm_check_state_set(ui->autofollow, ui->state.follow);
+ _clear_update(ui, elm_genlist_items_count(ui->list));
+ }
- // check item count
- if(n + 1 > ui->count_max)
+ break;
+ }
+ case 2:
+ {
+ const LV2_Atom_Tuple *tup = buf;
+ const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
+ const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
+ const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
+ int n = elm_genlist_items_count(ui->list);
+
+ Elm_Object_Item *itm = NULL;
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
{
- if(elm_check_state_get(ui->autoclear))
+ position_t *pos = malloc(sizeof(position_t));
+ if(!pos)
+ return;
+
+ pos->offset = offset->body;
+ pos->nsamples = nsamples->body;
+
+ // check item count
+ if(n + 1 > ui->state.count)
{
- elm_genlist_clear(ui->list);
- n = 0;
+ if(ui->state.overwrite)
+ {
+ elm_genlist_clear(ui->list);
+ n = 0;
+ }
+ else
+ {
+ return;
+ }
}
- else
+ else if(ui->state.block)
{
return;
}
- }
- else if(elm_check_state_get(ui->autoblock))
- {
- return;
- }
- itm = elm_genlist_item_append(ui->list, ui->itc_group,
- pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
- elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
+ itm = elm_genlist_item_append(ui->list, ui->itc_group,
+ pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
- LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
- {
- size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
- LV2_Atom_Event *ev = malloc(len);
- if(!ev)
- continue;
-
- memcpy(ev, elmnt, len);
-
- Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_list,
- ev, itm, ELM_GENLIST_ITEM_NONE, NULL, NULL);
- elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
- n++;
-
- if(n == 1) // always select first element
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
-
- if(elm_check_state_get(ui->autofollow)) // scroll to last item
+ LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
{
- elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
+ LV2_Atom_Event *ev = malloc(len);
+ if(!ev)
+ continue;
+
+ memcpy(ev, elmnt, len);
+
+ Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_list,
+ ev, itm, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
+ n++;
+
+ if(n == 1) // always select first element
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+
+ if(ui->state.follow) // scroll to last item
+ {
+ elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ }
}
}
+
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
+ _clear_update(ui, n); // only update if there where any events
+
+ break;
}
-
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
- _clear_update(ui, n); // only update if there where any events
}
}
diff --git a/midi_inspector.c b/midi_inspector.c
index 7c88f9f..8b8573c 100644
--- a/midi_inspector.c
+++ b/midi_inspector.c
@@ -36,6 +36,10 @@ struct _handle_t {
LV2_URID midi_event;
int64_t frame;
+
+ PROPS_T(props, MAX_NPROPS);
+ state_t state;
+ state_t stash;
};
static LV2_Handle
@@ -65,6 +69,22 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
lv2_atom_forge_init(&handle->forge, handle->map);
+ if(!props_init(&handle->props, MAX_NPROPS, descriptor->URI, handle->map, handle))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(handle);
+ return NULL;
+ }
+
+ if( !props_register(&handle->props, &stat_count, &handle->state.count, &handle->stash.count)
+ || !props_register(&handle->props, &stat_overwrite, &handle->state.overwrite, &handle->stash.overwrite)
+ || !props_register(&handle->props, &stat_block, &handle->state.block, &handle->stash.block)
+ || !props_register(&handle->props, &stat_follow, &handle->state.follow, &handle->stash.follow) )
+ {
+ free(handle);
+ return NULL;
+ }
+
return handle;
}
@@ -98,30 +118,41 @@ run(LV2_Handle instance, uint32_t nsamples)
LV2_Atom_Forge_Frame frame [3];
LV2_Atom_Forge_Ref ref;
+ // size of input sequence
+ const size_t size = lv2_atom_total_size(&handle->control_in->atom);
+
+ // copy whole input sequence to through port
+ capacity = handle->control_out->atom.size;
+ lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
+ ref = lv2_atom_forge_sequence_head(forge, frame, 0);
+
LV2_ATOM_SEQUENCE_FOREACH(handle->control_in, ev)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
-
- if(lv2_atom_forge_is_object_type(forge, obj->atom.type))
+ const int64_t frames = ev->time.frames;
+
+ // copy all events to through port
+ if(ref)
+ ref = lv2_atom_forge_frame_time(forge, frames);
+ if(ref)
+ ref = lv2_atom_forge_raw(forge, &obj->atom, lv2_atom_total_size(&obj->atom));
+ if(ref)
+ lv2_atom_forge_pad(forge, obj->atom.size);
+
+ if( !props_advance(&handle->props, forge, frames, obj, &ref)
+ && lv2_atom_forge_is_object_type(forge, obj->atom.type)
+ && (obj->body.otype == handle->time_position) )
{
- if(obj->body.otype == handle->time_position)
- {
- const LV2_Atom_Long *time_frame = NULL;
- lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
- if(time_frame)
- handle->frame = time_frame->body - ev->time.frames;
- }
+ const LV2_Atom_Long *time_frame = NULL;
+ lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
+ if(time_frame)
+ handle->frame = time_frame->body - frames;
}
}
- // size of input sequence
- size_t size = sizeof(LV2_Atom) + handle->control_in->atom.size;
-
- // copy whole input sequence to through port
- capacity = handle->control_out->atom.size;
- lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
- ref = lv2_atom_forge_raw(forge, handle->control_in, size);
- if(!ref)
+ if(ref)
+ lv2_atom_forge_pop(forge, frame);
+ else
lv2_atom_sequence_clear(handle->control_out);
// forge whole sequence as single event
@@ -178,6 +209,39 @@ cleanup(LV2_Handle instance)
free(handle);
}
+static LV2_State_Status
+_state_save(LV2_Handle instance, LV2_State_Store_Function store,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_save(&handle->props, &handle->forge, store, state, flags, features);
+}
+
+static LV2_State_Status
+_state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_restore(&handle->props, &handle->forge, retrieve, state, flags, features);
+}
+
+static const LV2_State_Interface state_iface = {
+ .save = _state_save,
+ .restore = _state_restore
+};
+
+static const void *
+extension_data(const char *uri)
+{
+ if(!strcmp(uri, LV2_STATE__interface))
+ return &state_iface;
+ return NULL;
+}
+
const LV2_Descriptor midi_inspector = {
.URI = SHERLOCK_MIDI_INSPECTOR_URI,
.instantiate = instantiate,
@@ -186,5 +250,5 @@ const LV2_Descriptor midi_inspector = {
.run = run,
.deactivate = NULL,
.cleanup = cleanup,
- .extension_data = NULL
+ .extension_data = extension_data
};
diff --git a/midi_inspector_eo.c b/midi_inspector_eo.c
index a325708..4dae485 100644
--- a/midi_inspector_eo.c
+++ b/midi_inspector_eo.c
@@ -48,7 +48,14 @@ struct _UI {
char string_buf [STRING_BUF_SIZE];
char *logo_path;
- int count_max;
+ PROPS_T(props, MAX_NPROPS);
+ struct {
+ LV2_URID overwrite;
+ LV2_URID block;
+ LV2_URID follow;
+ } urid;
+ state_t state;
+ state_t stash;
};
typedef struct _midi_msg_t midi_msg_t;
@@ -522,7 +529,7 @@ _clear_update(UI *ui, int count)
return;
char *buf = ui->string_buf;
- sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->count_max);
+ sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->state.count);
elm_object_text_set(ui->clear, buf);
}
@@ -568,6 +575,70 @@ _content_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
evas_object_del(ui->widget);
}
+static inline void
+_discover(UI *ui)
+{
+ union {
+ LV2_Atom atom;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+ LV2_Atom_Forge_Frame frame;
+
+ if(lv2_atom_forge_object(&ui->forge, &frame, 0, ui->props.urid.patch_get))
+ {
+ lv2_atom_forge_pop(&ui->forge, &frame);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.atom),
+ ui->event_transfer, &buf.atom);
+ }
+}
+
+static inline void
+_check_changed(UI *ui, LV2_URID property)
+{
+ union {
+ LV2_Atom_Event ev;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+
+ LV2_Atom_Forge_Ref ref = 1;
+ props_set(&ui->props, &ui->forge, 0, property, &ref);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.ev.body),
+ ui->event_transfer, &buf.ev.body);
+}
+
+static void
+_autoclear_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.overwrite = elm_check_state_get(ui->autoclear) ? 1 : 0;
+ _check_changed(ui, ui->urid.overwrite);
+}
+
+static void
+_autoblock_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.block = elm_check_state_get(ui->autoblock) ? 1 : 0;
+ _check_changed(ui, ui->urid.block);
+}
+
+static void
+_autofollow_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.follow = elm_check_state_get(ui->autofollow) ? 1 : 0;
+ _check_changed(ui, ui->urid.follow);
+}
+
static Evas_Object *
_content_get(UI *ui, Evas_Object *parent)
{
@@ -610,6 +681,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoclear)
{
elm_object_text_set(ui->autoclear, "overwrite");
+ evas_object_smart_callback_add(ui->autoclear, "changed", _autoclear_changed, ui);
evas_object_size_hint_weight_set(ui->autoclear, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoclear, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoclear);
@@ -620,6 +692,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoblock)
{
elm_object_text_set(ui->autoblock, "block");
+ evas_object_smart_callback_add(ui->autoblock, "changed", _autoblock_changed, ui);
evas_object_size_hint_weight_set(ui->autoblock, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoblock, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoblock);
@@ -630,6 +703,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autofollow)
{
elm_object_text_set(ui->autofollow, "follow");
+ evas_object_smart_callback_add(ui->autofollow, "changed", _autofollow_changed, ui);
evas_object_size_hint_weight_set(ui->autofollow, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autofollow, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autofollow);
@@ -780,8 +854,24 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
}
*(Evas_Object **)widget = ui->widget;
- ui->count_max = 2048;
-
+ if(!props_init(&ui->props, MAX_NPROPS, plugin_uri, ui->map, ui))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(ui);
+ return NULL;
+ }
+
+ if( !props_register(&ui->props, &stat_count, &ui->state.count, &ui->stash.count)
+ || !(ui->urid.overwrite = props_register(&ui->props, &stat_overwrite, &ui->state.overwrite, &ui->stash.overwrite))
+ || !(ui->urid.block = props_register(&ui->props, &stat_block, &ui->state.block, &ui->stash.block))
+ || !(ui->urid.follow = props_register(&ui->props, &stat_follow, &ui->state.follow, &ui->stash.follow)) )
+ {
+ free(ui);
+ return NULL;
+ }
+
+ _discover(ui);
+
return ui;
}
@@ -807,74 +897,96 @@ port_event(LV2UI_Handle handle, uint32_t i, uint32_t size, uint32_t urid,
const void *buf)
{
UI *ui = handle;
-
- if( (i == 2) && (urid == ui->event_transfer) && ui->list)
+
+ if(urid != ui->event_transfer)
+ return;
+
+ switch(i)
{
- const LV2_Atom_Tuple *tup = buf;
- const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
- const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
- const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
- int n = elm_genlist_items_count(ui->list);
-
- Elm_Object_Item *itm = NULL;
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
+ case 0:
+ case 1:
{
- position_t *pos = malloc(sizeof(position_t));
- if(!pos)
- return;
-
- pos->offset = offset->body;
- pos->nsamples = nsamples->body;
+ LV2_Atom_Forge_Ref ref = 1;
+ if(props_advance(&ui->props, &ui->forge, 0, (const LV2_Atom_Object *)buf, &ref))
+ {
+ elm_check_state_set(ui->autoclear, ui->state.overwrite);
+ elm_check_state_set(ui->autoblock, ui->state.block);
+ elm_check_state_set(ui->autofollow, ui->state.follow);
+ _clear_update(ui, elm_genlist_items_count(ui->list));
+ }
- // check item count
- if(n + 1 > ui->count_max)
+ break;
+ }
+ case 2:
+ {
+ const LV2_Atom_Tuple *tup = buf;
+ const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
+ const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
+ const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
+ int n = elm_genlist_items_count(ui->list);
+
+ Elm_Object_Item *itm = NULL;
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
{
- if(elm_check_state_get(ui->autoclear))
+ position_t *pos = malloc(sizeof(position_t));
+ if(!pos)
+ return;
+
+ pos->offset = offset->body;
+ pos->nsamples = nsamples->body;
+
+ // check item count
+ if(n + 1 > ui->state.count)
{
- elm_genlist_clear(ui->list);
- n = 0;
+ if(ui->state.overwrite)
+ {
+ elm_genlist_clear(ui->list);
+ n = 0;
+ }
+ else
+ {
+ return;
+ }
}
- else
+ else if(ui->state.block)
{
return;
}
- }
- else if(elm_check_state_get(ui->autoblock))
- {
- return;
- }
-
- itm = elm_genlist_item_append(ui->list, ui->itc_group,
- pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
- elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
- LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
- {
- size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
- LV2_Atom_Event *ev = malloc(len);
- if(!ev)
- continue;
+ itm = elm_genlist_item_append(ui->list, ui->itc_group,
+ pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
- memcpy(ev, elmnt, len);
-
- Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_midi,
- ev, itm, ELM_GENLIST_ITEM_NONE, NULL, NULL);
- elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
- n++;
+ LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
+ {
+ size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
+ LV2_Atom_Event *ev = malloc(len);
+ if(!ev)
+ continue;
- if(n == 1) // always select first element
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ memcpy(ev, elmnt, len);
- if(elm_check_state_get(ui->autofollow)) // scroll to last item
- {
- elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_midi,
+ ev, itm, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
+ n++;
+
+ if(n == 1) // always select first element
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+
+ if(ui->state.follow) // scroll to last item
+ {
+ elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ }
}
}
+
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
+ _clear_update(ui, n); // only update if there where any events
+
+ break;
}
-
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
- _clear_update(ui, n); // only update if there where any events
}
}
diff --git a/osc_inspector.c b/osc_inspector.c
index c6b5ae8..ef9622a 100644
--- a/osc_inspector.c
+++ b/osc_inspector.c
@@ -37,6 +37,10 @@ struct _handle_t {
LV2_OSC_URID osc_urid;
int64_t frame;
+
+ PROPS_T(props, MAX_NPROPS);
+ state_t state;
+ state_t stash;
};
static LV2_Handle
@@ -65,6 +69,22 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
lv2_osc_urid_init(&handle->osc_urid, handle->map);
lv2_atom_forge_init(&handle->forge, handle->map);
+ if(!props_init(&handle->props, MAX_NPROPS, descriptor->URI, handle->map, handle))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(handle);
+ return NULL;
+ }
+
+ if( !props_register(&handle->props, &stat_count, &handle->state.count, &handle->stash.count)
+ || !props_register(&handle->props, &stat_overwrite, &handle->state.overwrite, &handle->stash.overwrite)
+ || !props_register(&handle->props, &stat_block, &handle->state.block, &handle->stash.block)
+ || !props_register(&handle->props, &stat_follow, &handle->state.follow, &handle->stash.follow) )
+ {
+ free(handle);
+ return NULL;
+ }
+
return handle;
}
@@ -98,30 +118,41 @@ run(LV2_Handle instance, uint32_t nsamples)
LV2_Atom_Forge_Frame frame [3];
LV2_Atom_Forge_Ref ref;
+ // size of input sequence
+ const size_t size = lv2_atom_total_size(&handle->control_in->atom);
+
+ // copy whole input sequence to through port
+ capacity = handle->control_out->atom.size;
+ lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
+ ref = lv2_atom_forge_sequence_head(forge, frame, 0);
+
LV2_ATOM_SEQUENCE_FOREACH(handle->control_in, ev)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
+ const int64_t frames = ev->time.frames;
- if(lv2_atom_forge_is_object_type(forge, obj->atom.type))
+ // copy all events to through port
+ if(ref)
+ ref = lv2_atom_forge_frame_time(forge, frames);
+ if(ref)
+ ref = lv2_atom_forge_raw(forge, &obj->atom, lv2_atom_total_size(&obj->atom));
+ if(ref)
+ lv2_atom_forge_pad(forge, obj->atom.size);
+
+ if( !props_advance(&handle->props, forge, frames, obj, &ref)
+ && lv2_atom_forge_is_object_type(forge, obj->atom.type)
+ && (obj->body.otype == handle->time_position) )
{
- if(obj->body.otype == handle->time_position)
- {
- const LV2_Atom_Long *time_frame = NULL;
- lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
- if(time_frame)
- handle->frame = time_frame->body - ev->time.frames;
- }
+ const LV2_Atom_Long *time_frame = NULL;
+ lv2_atom_object_get(obj, handle->time_frame, &time_frame, NULL);
+ if(time_frame)
+ handle->frame = time_frame->body - frames;
}
}
- // size of input sequence
- size_t size = sizeof(LV2_Atom) + handle->control_in->atom.size;
-
- // copy whole input sequence to through port
- capacity = handle->control_out->atom.size;
- lv2_atom_forge_set_buffer(forge, (uint8_t *)handle->control_out, capacity);
- ref = lv2_atom_forge_raw(forge, handle->control_in, size);
- if(!ref)
+ if(ref)
+ lv2_atom_forge_pop(forge, frame);
+ else
lv2_atom_sequence_clear(handle->control_out);
// forge whole sequence as single event
@@ -180,6 +211,39 @@ cleanup(LV2_Handle instance)
free(handle);
}
+static LV2_State_Status
+_state_save(LV2_Handle instance, LV2_State_Store_Function store,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_save(&handle->props, &handle->forge, store, state, flags, features);
+}
+
+static LV2_State_Status
+_state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
+ LV2_State_Handle state, uint32_t flags,
+ const LV2_Feature *const *features)
+{
+ handle_t *handle = instance;
+
+ return props_restore(&handle->props, &handle->forge, retrieve, state, flags, features);
+}
+
+static const LV2_State_Interface state_iface = {
+ .save = _state_save,
+ .restore = _state_restore
+};
+
+static const void *
+extension_data(const char *uri)
+{
+ if(!strcmp(uri, LV2_STATE__interface))
+ return &state_iface;
+ return NULL;
+}
+
const LV2_Descriptor osc_inspector = {
.URI = SHERLOCK_OSC_INSPECTOR_URI,
.instantiate = instantiate,
@@ -188,5 +252,5 @@ const LV2_Descriptor osc_inspector = {
.run = run,
.deactivate = NULL,
.cleanup = cleanup,
- .extension_data = NULL
+ .extension_data = extension_data
};
diff --git a/osc_inspector_eo.c b/osc_inspector_eo.c
index 33056ea..d1a3ee6 100644
--- a/osc_inspector_eo.c
+++ b/osc_inspector_eo.c
@@ -56,7 +56,14 @@ struct _UI {
char string_buf [STRING_BUF_SIZE];
char *logo_path;
- int count_max;
+ PROPS_T(props, MAX_NPROPS);
+ struct {
+ LV2_URID overwrite;
+ LV2_URID block;
+ LV2_URID follow;
+ } urid;
+ state_t state;
+ state_t stash;
};
// there is a bug in LV2 <= 0.10
@@ -584,7 +591,7 @@ _clear_update(UI *ui, int count)
return;
char *buf = ui->string_buf;
- sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->count_max);
+ sprintf(buf, "Clear (%"PRIi32" of %"PRIi32")", count, ui->state.count);
elm_object_text_set(ui->clear, buf);
}
@@ -630,6 +637,70 @@ _content_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
evas_object_del(ui->widget);
}
+static inline void
+_discover(UI *ui)
+{
+ union {
+ LV2_Atom atom;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+ LV2_Atom_Forge_Frame frame;
+
+ if(lv2_atom_forge_object(&ui->forge, &frame, 0, ui->props.urid.patch_get))
+ {
+ lv2_atom_forge_pop(&ui->forge, &frame);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.atom),
+ ui->event_transfer, &buf.atom);
+ }
+}
+
+static inline void
+_check_changed(UI *ui, LV2_URID property)
+{
+ union {
+ LV2_Atom_Event ev;
+ uint8_t raw [128];
+ } buf;
+
+ lv2_atom_forge_set_buffer(&ui->forge, buf.raw, 512);
+
+ LV2_Atom_Forge_Ref ref = 1;
+ props_set(&ui->props, &ui->forge, 0, property, &ref);
+
+ ui->write_function(ui->controller, 0, lv2_atom_total_size(&buf.ev.body),
+ ui->event_transfer, &buf.ev.body);
+}
+
+static void
+_autoclear_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.overwrite = elm_check_state_get(ui->autoclear) ? 1 : 0;
+ _check_changed(ui, ui->urid.overwrite);
+}
+
+static void
+_autoblock_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.block = elm_check_state_get(ui->autoblock) ? 1 : 0;
+ _check_changed(ui, ui->urid.block);
+}
+
+static void
+_autofollow_changed(void *data, Evas_Object *obj, void *event)
+{
+ UI *ui = data;
+
+ ui->state.follow = elm_check_state_get(ui->autofollow) ? 1 : 0;
+ _check_changed(ui, ui->urid.follow);
+}
+
static Evas_Object *
_content_get(UI *ui, Evas_Object *parent)
{
@@ -678,6 +749,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoclear)
{
elm_object_text_set(ui->autoclear, "overwrite");
+ evas_object_smart_callback_add(ui->autoclear, "changed", _autoclear_changed, ui);
evas_object_size_hint_weight_set(ui->autoclear, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoclear, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoclear);
@@ -688,6 +760,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autoblock)
{
elm_object_text_set(ui->autoblock, "block");
+ evas_object_smart_callback_add(ui->autoblock, "changed", _autoblock_changed, ui);
evas_object_size_hint_weight_set(ui->autoblock, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autoblock, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autoblock);
@@ -698,6 +771,7 @@ _content_get(UI *ui, Evas_Object *parent)
if(ui->autofollow)
{
elm_object_text_set(ui->autofollow, "follow");
+ evas_object_smart_callback_add(ui->autofollow, "changed", _autofollow_changed, ui);
evas_object_size_hint_weight_set(ui->autofollow, 0.f, 0.f);
evas_object_size_hint_align_set(ui->autofollow, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(ui->autofollow);
@@ -862,7 +936,23 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
}
*(Evas_Object **)widget = ui->widget;
- ui->count_max = 2048;
+ if(!props_init(&ui->props, MAX_NPROPS, plugin_uri, ui->map, ui))
+ {
+ fprintf(stderr, "failed to allocate property structure\n");
+ free(ui);
+ return NULL;
+ }
+
+ if( !props_register(&ui->props, &stat_count, &ui->state.count, &ui->stash.count)
+ || !(ui->urid.overwrite = props_register(&ui->props, &stat_overwrite, &ui->state.overwrite, &ui->stash.overwrite))
+ || !(ui->urid.block = props_register(&ui->props, &stat_block, &ui->state.block, &ui->stash.block))
+ || !(ui->urid.follow = props_register(&ui->props, &stat_follow, &ui->state.follow, &ui->stash.follow)) )
+ {
+ free(ui);
+ return NULL;
+ }
+
+ _discover(ui);
return ui;
}
@@ -890,75 +980,97 @@ port_event(LV2UI_Handle handle, uint32_t i, uint32_t size, uint32_t urid,
const void *buf)
{
UI *ui = handle;
-
- if( (i == 2) && (urid == ui->event_transfer) && ui->list)
+
+ if(urid != ui->event_transfer)
+ return;
+
+ switch(i)
{
- const LV2_Atom_Tuple *tup = buf;
- const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
- const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
- const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
- int n = elm_genlist_items_count(ui->list);
-
- Elm_Object_Item *itm = NULL;
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
+ case 0:
+ case 1:
{
- position_t *pos = malloc(sizeof(position_t));
- if(!pos)
- return;
-
- pos->offset = offset->body;
- pos->nsamples = nsamples->body;
+ LV2_Atom_Forge_Ref ref = 1;
+ if(props_advance(&ui->props, &ui->forge, 0, (const LV2_Atom_Object *)buf, &ref))
+ {
+ elm_check_state_set(ui->autoclear, ui->state.overwrite);
+ elm_check_state_set(ui->autoblock, ui->state.block);
+ elm_check_state_set(ui->autofollow, ui->state.follow);
+ _clear_update(ui, elm_genlist_items_count(ui->list));
+ }
- // check item count
- if(n + 1 > ui->count_max)
+ break;
+ }
+ case 2:
+ {
+ const LV2_Atom_Tuple *tup = buf;
+ const LV2_Atom_Long *offset = (const LV2_Atom_Long *)lv2_atom_tuple_begin(tup);
+ const LV2_Atom_Int *nsamples = (const LV2_Atom_Int *)lv2_atom_tuple_next(&offset->atom);
+ const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)lv2_atom_tuple_next(&nsamples->atom);
+ int n = elm_genlist_items_count(ui->list);
+
+ Elm_Object_Item *itm = NULL;
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) // there are events
{
- if(elm_check_state_get(ui->autoclear))
+ position_t *pos = malloc(sizeof(position_t));
+ if(!pos)
+ return;
+
+ pos->offset = offset->body;
+ pos->nsamples = nsamples->body;
+
+ // check item count
+ if(n + 1 > ui->state.count)
{
- elm_genlist_clear(ui->list);
- n = 0;
+ if(ui->state.overwrite)
+ {
+ elm_genlist_clear(ui->list);
+ n = 0;
+ }
+ else
+ {
+ return;
+ }
}
- else
+ else if(ui->state.block)
{
return;
}
- }
- else if(elm_check_state_get(ui->autoblock))
- {
- return;
- }
-
- itm = elm_genlist_item_append(ui->list, ui->itc_group,
- pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
- elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
-
- LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
- {
- size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
- LV2_Atom_Event *ev = malloc(len);
- if(!ev)
- continue;
- memcpy(ev, elmnt, len);
+ itm = elm_genlist_item_append(ui->list, ui->itc_group,
+ pos, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm, ELM_OBJECT_SELECT_MODE_NONE);
- Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_packet,
- ev, itm, ELM_GENLIST_ITEM_TREE, NULL, NULL);
- elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
- elm_genlist_item_expanded_set(itm2, EINA_FALSE);
- n++;
-
- if(n == 1) // always select first element
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
-
- if(elm_check_state_get(ui->autofollow)) // scroll to last item
+ LV2_ATOM_SEQUENCE_FOREACH(seq, elmnt)
{
- elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
- elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ size_t len = sizeof(LV2_Atom_Event) + elmnt->body.size;
+ LV2_Atom_Event *ev = malloc(len);
+ if(!ev)
+ continue;
+
+ memcpy(ev, elmnt, len);
+
+ Elm_Object_Item *itm2 = elm_genlist_item_append(ui->list, ui->itc_packet,
+ ev, itm, ELM_GENLIST_ITEM_TREE, NULL, NULL);
+ elm_genlist_item_select_mode_set(itm2, ELM_OBJECT_SELECT_MODE_DEFAULT);
+ elm_genlist_item_expanded_set(itm2, EINA_FALSE);
+ n++;
+
+ if(n == 1) // always select first element
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+
+ if(ui->state.follow) // scroll to last item
+ {
+ elm_genlist_item_show(itm2, ELM_GENLIST_ITEM_SCROLLTO_BOTTOM);
+ elm_genlist_item_selected_set(itm2, EINA_TRUE);
+ }
}
}
- }
- if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
- _clear_update(ui, n); // only update if there where any events
+ if(seq->atom.size > sizeof(LV2_Atom_Sequence_Body))
+ _clear_update(ui, n); // only update if there where any events
+
+ break;
+ }
}
}
diff --git a/sherlock.h b/sherlock.h
index b303b85..d551d5b 100644
--- a/sherlock.h
+++ b/sherlock.h
@@ -30,6 +30,9 @@
#include "lv2/lv2plug.in/ns/extensions/units/units.h"
#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#include <stdio.h>
+#include <props.h>
#define LV2_OSC__OscEvent "http://opensoundcontrol.org#OscEvent"
@@ -66,10 +69,48 @@ extern const LV2UI_Descriptor osc_inspector_kx;
extern const LV2UI_Descriptor osc_inspector_eo;
typedef struct _position_t position_t;
+typedef struct _state_t state_t;
struct _position_t {
uint64_t offset;
uint32_t nsamples;
};
+struct _state_t {
+ int32_t count;
+ int32_t overwrite;
+ int32_t block;
+ int32_t follow;
+};
+
+#define MAX_NPROPS 4
+
+static const props_def_t stat_count = {
+ .property = SHERLOCK_URI"#count",
+ .access = LV2_PATCH__writable,
+ .type = LV2_ATOM__Int,
+ .mode = PROP_MODE_STATIC
+};
+
+static const props_def_t stat_overwrite = {
+ .property = SHERLOCK_URI"#overwrite",
+ .access = LV2_PATCH__writable,
+ .type = LV2_ATOM__Bool,
+ .mode = PROP_MODE_STATIC
+};
+
+static const props_def_t stat_block = {
+ .property = SHERLOCK_URI"#block",
+ .access = LV2_PATCH__writable,
+ .type = LV2_ATOM__Bool,
+ .mode = PROP_MODE_STATIC
+};
+
+static const props_def_t stat_follow = {
+ .property = SHERLOCK_URI"#follow",
+ .access = LV2_PATCH__writable,
+ .type = LV2_ATOM__Bool,
+ .mode = PROP_MODE_STATIC
+};
+
#endif // _SHERLOCK_LV2_H
diff --git a/sherlock.ttl b/sherlock.ttl
index 834f648..82b0549 100644
--- a/sherlock.ttl
+++ b/sherlock.ttl
@@ -16,19 +16,22 @@
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix time: <http://lv2plug.in/ns/ext/time#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
+@prefix state: <http://lv2plug.in/ns/ext/state#> .
@prefix xpress: <http://open-music-kontrollers.ch/lv2/xpress#> .
-@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
-@prefix lic: <http://opensource.org/licenses/> .
-@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
+@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
+@prefix lic: <http://opensource.org/licenses/> .
+@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
@prefix proj: <http://open-music-kontrollers.ch/lv2/> .
-@prefix sherlock: <http://open-music-kontrollers.ch/lv2/sherlock#> .
+@prefix sherlock: <http://open-music-kontrollers.ch/lv2/sherlock#> .
osc:Event
a rdfs:Class ;
@@ -53,6 +56,35 @@ proj:sherlock
doap:maintainer omk:me ;
doap:name "Sherlock Bundle" .
+sherlock:count
+ a lv2:Parameter ;
+ rdfs:label "Max. events" ;
+ rdfs:comment "Maximum number of events shown" ;
+ rdfs:range atom:Int ;
+ lv2:scalePoint [ rdfs:label "1k" ; rdf:value 1024 ] ;
+ lv2:scalePoint [ rdfs:label "2k" ; rdf:value 2048 ] ;
+ lv2:scalePoint [ rdfs:label "4k" ; rdf:value 4096 ] ;
+ lv2:scalePoint [ rdfs:label "8k" ; rdf:value 8192 ] ;
+ lv2:scalePoint [ rdfs:label "16k" ; rdf:value 16384 ] .
+
+sherlock:overwrite
+ a lv2:Parameter ;
+ rdfs:label "Overwrite" ;
+ rdfs:comment "Overwrite buffer when maximum number of events reached" ;
+ rdfs:range atom:Bool .
+
+sherlock:block
+ a lv2:Parameter ;
+ rdfs:label "Block" ;
+ rdfs:comment "Block addition of newly received events" ;
+ rdfs:range atom:Bool .
+
+sherlock:follow
+ a lv2:Parameter ;
+ rdfs:label "Follow" ;
+ rdfs:comment "Automatically scroll to and show last added event" ;
+ rdfs:range atom:Bool .
+
# Atom Inspector Plugin
sherlock:atom_inspector
a lv2:Plugin,
@@ -61,7 +93,8 @@ sherlock:atom_inspector
doap:license lic:Artistic-2.0 ;
lv2:project proj:sherlock ;
lv2:optionalFeature lv2:isLive, lv2:hardRTCapable ;
- lv2:requiredFeature urid:map ;
+ lv2:requiredFeature urid:map, state:loadDefaultState ;
+ lv2:extensionData state:interface;
lv2:port [
# input event port
@@ -100,6 +133,19 @@ sherlock:atom_inspector
lv2:index 2 ;
lv2:symbol "notify" ;
lv2:name "Notify" ;
+ ] ;
+
+ patch:writable
+ sherlock:count ,
+ sherlock:overwrite,
+ sherlock:block ,
+ sherlock:follow ;
+
+ state:state [
+ sherlock:count 2048 ;
+ sherlock:overwrite false ;
+ sherlock:block false ;
+ sherlock:follow false ;
] .
# MIDI Inspector Plugin
@@ -110,7 +156,8 @@ sherlock:midi_inspector
doap:license lic:Artistic-2.0 ;
lv2:project proj:sherlock ;
lv2:optionalFeature lv2:isLive, lv2:hardRTCapable ;
- lv2:requiredFeature urid:map ;
+ lv2:requiredFeature urid:map, state:loadDefaultState ;
+ lv2:extensionData state:interface;
lv2:port [
# input event port
@@ -118,6 +165,7 @@ sherlock:midi_inspector
atom:AtomPort ;
atom:bufferType atom:Sequence ;
atom:supports midi:MidiEvent ,
+ patch:Message ,
time:Position ;
lv2:index 0 ;
lv2:symbol "control_in" ;
@@ -128,7 +176,8 @@ sherlock:midi_inspector
a lv2:OutputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports midi:MidiEvent ;
+ atom:supports midi:MidiEvent ,
+ patch:Message ;
lv2:index 1 ;
lv2:symbol "control_out" ;
lv2:name "Control Out" ;
@@ -142,6 +191,19 @@ sherlock:midi_inspector
lv2:index 2 ;
lv2:symbol "notify" ;
lv2:name "Notify" ;
+ ] ;
+
+ patch:writable
+ sherlock:count ,
+ sherlock:overwrite ,
+ sherlock:block ,
+ sherlock:follow ;
+
+ state:state [
+ sherlock:count 2048 ;
+ sherlock:overwrite false ;
+ sherlock:block false ;
+ sherlock:follow false ;
] .
# OSC Inspector Plugin
@@ -152,7 +214,8 @@ sherlock:osc_inspector
doap:license lic:Artistic-2.0 ;
lv2:project proj:sherlock ;
lv2:optionalFeature lv2:isLive, lv2:hardRTCapable ;
- lv2:requiredFeature urid:map ;
+ lv2:requiredFeature urid:map, state:loadDefaultState ;
+ lv2:extensionData state:interface;
lv2:port [
# input event port
@@ -160,6 +223,7 @@ sherlock:osc_inspector
atom:AtomPort ;
atom:bufferType atom:Sequence ;
atom:supports osc:Event ,
+ patch:Message ,
time:Position ;
lv2:index 0 ;
lv2:symbol "control_in" ;
@@ -170,7 +234,8 @@ sherlock:osc_inspector
a lv2:OutputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports osc:Event ;
+ atom:supports osc:Event ,
+ patch:Message ;
lv2:index 1 ;
lv2:symbol "control_out" ;
lv2:name "Control Out" ;
@@ -184,4 +249,17 @@ sherlock:osc_inspector
lv2:index 2 ;
lv2:symbol "notify" ;
lv2:name "Notify" ;
+ ] ;
+
+ patch:writable
+ sherlock:count ,
+ sherlock:overwrite ,
+ sherlock:block ,
+ sherlock:follow ;
+
+ state:state [
+ sherlock:count 2048 ;
+ sherlock:overwrite false ;
+ sherlock:block false ;
+ sherlock:follow false ;
] .