aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-21 20:51:07 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-21 20:51:07 +0100
commitd0f3a9ac228f5798a045f75376817b43666939bd (patch)
tree324f4540c6fd7413777a75611a447412e6790107
parentf3d77a9c079754914ebe1ccdfc58d0df953be8b8 (diff)
downloadvm.lv2-d0f3a9ac228f5798a045f75376817b43666939bd.tar.xz
plot control values.
-rw-r--r--VERSION2
-rw-r--r--vm.c31
-rw-r--r--vm.ttl4
-rw-r--r--vm_ui.c235
4 files changed, 180 insertions, 92 deletions
diff --git a/VERSION b/VERSION
index 9ce3f90..64b494f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.2845
+0.1.2847
diff --git a/vm.c b/vm.c
index da5adf4..1fd989e 100644
--- a/vm.c
+++ b/vm.c
@@ -69,6 +69,8 @@ struct _plughandle_t {
bool needs_sync;
bool uses_time;
+ int64_t off;
+
command_t cmds [ITEMS_MAX];
timely_t timely;
@@ -661,13 +663,38 @@ run(LV2_Handle instance, uint32_t nsamples)
handle->needs_recalc = false;
}
+ //FIXME handle also inputs
+ for(unsigned i = 0; i < CTRL_MAX; i++)
+ {
+ if(*handle->out[i] != handle->out0[i])
+ {
+ *handle->out[i] = handle->out0[i];;
+
+ LV2_Atom_Forge_Frame tup_frame;
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_frame_time(&handle->forge, nsamples - 1);
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_tuple(&handle->forge, &tup_frame);
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_int(&handle->forge, i + 10);
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_float(&handle->forge, handle->out0[i]);
+ if(handle->ref)
+ lv2_atom_forge_pop(&handle->forge, &tup_frame);
+ }
+ }
+
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_frame_time(&handle->forge, nsamples - 1);
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_long(&handle->forge, handle->off);
+
if(handle->ref)
lv2_atom_forge_pop(&handle->forge, &frame);
else
lv2_atom_sequence_clear(handle->notify);
- for(unsigned i = 0; i < CTRL_MAX; i++)
- *handle->out[i] = handle->out0[i];;
+ handle->off += nsamples;
}
static void
diff --git a/vm.ttl b/vm.ttl
index be17448..6e4a81d 100644
--- a/vm.ttl
+++ b/vm.ttl
@@ -353,8 +353,8 @@ vm:lfo
vm:graph [
a atom:Tuple ;
rdf:value (
- # Phase := (Beat % Control0 ) / Control0
- 0 vm:opInput
+ # Phase := (Beat % Cycles) / Control0
+ 2.0 # Cycles per beat
vm:opPush
time:beat
vm:opSwap
diff --git a/vm_ui.c b/vm_ui.c
index 021f3b3..8e36479 100644
--- a/vm_ui.c
+++ b/vm_ui.c
@@ -31,7 +31,10 @@
# undef Bool
#endif
+#define PLOT_MAX 256
+
typedef struct _atom_ser_t atom_ser_t;
+typedef struct _plot_t plot_t;
typedef struct _plughandle_t plughandle_t;
struct _atom_ser_t {
@@ -44,6 +47,10 @@ struct _atom_ser_t {
};
};
+struct _plot_t {
+ float vals [PLOT_MAX];
+};
+
struct _plughandle_t {
LV2_URID_Map *map;
LV2_URID_Unmap *unmap;
@@ -74,15 +81,22 @@ struct _plughandle_t {
float in0 [CTRL_MAX];
float out0 [CTRL_MAX];
+ int64_t off;
+ plot_t inp [CTRL_MAX];
+ plot_t outp [CTRL_MAX];
+
command_t cmds [ITEMS_MAX];
};
-typedef struct _desc_t desc_t;
-
-struct _desc_t {
- const char *label;
- unsigned npush;
- unsigned npop;
+static const char *input_labels [CTRL_MAX] = {
+ "Input 0:",
+ "Input 1:",
+ "Input 2:",
+ "Input 3:",
+ "Input 4:",
+ "Input 5:",
+ "Input 6:",
+ "Input 7:",
};
static void
@@ -176,26 +190,45 @@ _set_property(plughandle_t *handle, LV2_URID property)
handle->atom_eventTransfer, atom);
}
-static bool
-_tooltip_visible(struct nk_context *ctx)
-{
- return nk_widget_has_mouse_click_down(ctx, NK_BUTTON_RIGHT, nk_true)
- || (nk_widget_is_hovered(ctx) && nk_input_is_key_down(&ctx->input, NK_KEY_CTRL));
-}
+#define VM_MIN -0x2000
+#define VM_MAX 0x1fff
+#define VM_RNG (VM_MAX - VM_MIN)
+#define VM_VIS (VM_RNG * 1.1f)
static inline void
-_draw_separator(struct nk_context *ctx, float line_width)
+_draw_plot(struct nk_context *ctx, const float *vals, unsigned nvals)
{
- const struct nk_rect b = nk_widget_bounds(ctx);
- const float x0 = b.x;
- const float x1 = b.x + b.w;
- const float y = b.y + b.h;
struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
- nk_stroke_line(canvas, x0, y, x1, y, line_width, ctx->style.window.background);
-}
-#define VM_MIN -0x2000
-#define VM_MAX 0x1fff
+ struct nk_rect bounds;
+ const nk_flags states = nk_widget(&bounds, ctx);
+ if(states != NK_WIDGET_INVALID)
+ {
+ const struct nk_rect old_clip = canvas->clip;
+
+ const struct nk_rect outer = nk_pad_rect(bounds, nk_vec2(-2.f, -2.f));
+ nk_push_scissor(canvas, outer);
+ nk_fill_rect(canvas, bounds, 0.f, nk_rgb(0x22, 0x22, 0x22));
+ nk_stroke_rect(canvas, bounds, 0.f, 1.f, ctx->style.window.border_color);
+
+ float mem [PLOT_MAX*2];
+ for(unsigned i = 0; i < nvals; i++)
+ {
+ const float sx = (float)i / nvals;
+ const float sy = vals[i] / VM_VIS;
+
+ const float x1 = bounds.x + sx*bounds.w;
+ const float y1 = bounds.y + (0.5f - sy)*bounds.h;
+
+ const unsigned i2 = i*2;
+ mem[i2 + 0] = x1;
+ mem[i2 + 1] = y1;
+ }
+
+ nk_stroke_polyline(canvas, mem, PLOT_MAX, 1.f, nk_rgb(0xcc, 0xcc, 0xcc));
+ nk_push_scissor(canvas, old_clip);
+ }
+}
static void
_expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
@@ -213,38 +246,22 @@ _expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
const float wh = wbounds.h
- 2*ctx->style.window.padding.y
- 2*ctx->style.window.border;
- nk_layout_row_dynamic(ctx, wh, 2);
- if(nk_group_begin(ctx, "Controls", NK_WINDOW_TITLE | NK_WINDOW_BORDER))
- {
- if(nk_tree_push(ctx, NK_TREE_NODE, "Inputs", NK_MAXIMIZED))
- {
- for(unsigned i = 0; i < CTRL_MAX; i++)
- {
- char label [16];
- snprintf(label, 16, "Input %u:", i);
-
- const float old_val = handle->in0[i];
- nk_property_float(ctx, label, VM_MIN, &handle->in0[i], VM_MAX, 1.f, 1.f);
- nk_slider_float(ctx, VM_MIN, &handle->in0[i], VM_MAX, 1.f);
- if(old_val != handle->in0[i])
- handle->writer(handle->controller, i + 2, sizeof(float), 0, &handle->in0[i]);
- }
- nk_tree_pop(ctx);
- }
+ const float ratio [3] = {0.25f, 0.5f, 0.25f};
+ nk_layout_row(ctx, NK_DYNAMIC, wh, 3, ratio);
- nk_spacing(ctx, 1);
-
- if(nk_tree_push(ctx, NK_TREE_NODE, "Outputs", NK_MAXIMIZED))
+ if(nk_group_begin(ctx, "Inputs", NK_WINDOW_TITLE | NK_WINDOW_BORDER))
+ {
+ for(unsigned i = 0; i < CTRL_MAX; i++)
{
- for(unsigned i = 0; i < CTRL_MAX; i++)
- {
- char label [16];
- snprintf(label, 16, "Output %u", i);
- nk_value_float(ctx, label, handle->out0[i]);
- nk_slide_float(ctx, VM_MIN, handle->out0[i], VM_MAX, 1.f);
- }
- nk_tree_pop(ctx);
+ nk_layout_row_dynamic(ctx, dy*4, 1);
+ _draw_plot(ctx, handle->inp[i].vals, PLOT_MAX);
+
+ nk_layout_row_dynamic(ctx, dy, 1);
+ const float old_val = handle->in0[i];
+ nk_property_float(ctx, input_labels[i], VM_MIN, &handle->in0[i], VM_MAX, 1.f, 1.f);
+ if(old_val != handle->in0[i])
+ handle->writer(handle->controller, i + 2, sizeof(float), 0, &handle->in0[i]);
}
nk_group_end(ctx);
@@ -382,6 +399,20 @@ _expose(struct nk_context *ctx, struct nk_rect wbounds, void *data)
nk_group_end(ctx);
}
+
+ if(nk_group_begin(ctx, "Outputs", NK_WINDOW_TITLE | NK_WINDOW_BORDER))
+ {
+ for(unsigned i = 0; i < CTRL_MAX; i++)
+ {
+ nk_layout_row_dynamic(ctx, dy*4, 1);
+ _draw_plot(ctx, handle->outp[i].vals, PLOT_MAX);
+
+ nk_layout_row_dynamic(ctx, dy, 1);
+ nk_labelf(ctx, NK_TEXT_LEFT, "Output %u: %+f", i, handle->out0[i]);
+ }
+
+ nk_group_end(ctx);
+ }
}
nk_end(ctx);
@@ -512,49 +543,79 @@ port_event(LV2UI_Handle instance, uint32_t index, uint32_t size,
{
if(protocol == handle->atom_eventTransfer)
{
- const LV2_Atom_Object *obj = buf;
+ const LV2_Atom *atom = buf;
- atom_ser_t *ser = &handle->ser;
- ser->offset = 0;
- lv2_atom_forge_set_sink(&handle->forge, _sink, _deref, ser);
+ if(atom->type == handle->forge.Long)
+ {
+ const LV2_Atom_Long *off = buf;
+
+ const int64_t dt = off->body - handle->off;
+ handle->off = off->body;
- LV2_Atom_Forge_Ref ref;
- if(props_advance(&handle->props, &handle->forge, 0, obj, &ref))
+ const float rate = 48000.f / dt; //FIXME
+ const unsigned ntimes = 4; //FIXME
+ const unsigned window = ceilf(PLOT_MAX / rate / ntimes);
+ const unsigned remainder = PLOT_MAX - window;
+
+ float mem [PLOT_MAX];
+ bool needs_refresh = false;
+
+ for(unsigned i = 0; i < CTRL_MAX; i++)
+ {
+ // inputs
+ {
+ memcpy(mem, &handle->inp[i].vals[window], sizeof(float)*remainder);
+ for(unsigned j = remainder; j < PLOT_MAX; j++)
+ mem[j] = handle->in0[i];
+
+ //FIXME can be made more efficient
+ if(memcmp(handle->inp[i].vals, mem, sizeof(float)*PLOT_MAX))
+ needs_refresh = true;
+
+ memcpy(handle->inp[i].vals, mem, sizeof(float)*PLOT_MAX);
+ }
+
+ // outputs
+ {
+ memcpy(mem, &handle->outp[i].vals[window], sizeof(float)*remainder);
+ for(unsigned j = remainder; j < PLOT_MAX; j++)
+ mem[j] = handle->out0[i];
+
+ //FIXME can be made more efficient
+ if(memcmp(handle->outp[i].vals, mem, sizeof(float)*PLOT_MAX))
+ needs_refresh = true;
+
+ memcpy(handle->outp[i].vals, mem, sizeof(float)*PLOT_MAX);
+ }
+ }
+
+ if(needs_refresh)
+ nk_pugl_post_redisplay(&handle->win);
+ }
+ else if(atom->type == handle->forge.Tuple)
{
- nk_pugl_post_redisplay(&handle->win);
+ const LV2_Atom_Int *idx = buf + 8;
+ const LV2_Atom_Float *val = buf + 8 + 16;
+
+ if(idx->body < 10)
+ handle->in0[idx->body - 2] = val->body;
+ else
+ handle->out0[idx->body - 10] = val->body;
}
- }
- } break;
+ else // !tuple
+ {
+ const LV2_Atom_Object *obj = buf;
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- {
- if(protocol == 0)
- {
- handle->in0[index - 2] = *(const float *)buf;
- nk_pugl_post_redisplay(&handle->win);
- }
- } break;
+ atom_ser_t *ser = &handle->ser;
+ ser->offset = 0;
+ lv2_atom_forge_set_sink(&handle->forge, _sink, _deref, ser);
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- {
- if(protocol == 0)
- {
- handle->out0[index - 10] = *(const float *)buf;
- nk_pugl_post_redisplay(&handle->win);
+ LV2_Atom_Forge_Ref ref;
+ if(props_advance(&handle->props, &handle->forge, 0, obj, &ref))
+ {
+ nk_pugl_post_redisplay(&handle->win);
+ }
+ }
}
} break;
}