aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/CMakeLists.txt1
-rw-r--r--data/smart_bitmask.edc185
-rw-r--r--data/synthpod.edc1
-rw-r--r--lib/CMakeLists.txt3
-rw-r--r--lib/smart_bitmask.c341
-rw-r--r--lib/smart_bitmask.h44
-rw-r--r--lib/smart_meter.c2
-rw-r--r--lib/smart_spinner.c2
-rw-r--r--lib/smart_toggle.c2
-rw-r--r--lib/synthpod_private.h11
-rw-r--r--lib/synthpod_ui.c176
11 files changed, 741 insertions, 27 deletions
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 8a85ae62..41eea0da 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -23,6 +23,7 @@ add_custom_command(
${CMAKE_CURRENT_SOURCE_DIR}/smart_meter.edc
${CMAKE_CURRENT_SOURCE_DIR}/smart_spinner.edc
${CMAKE_CURRENT_SOURCE_DIR}/smart_toggle.edc
+ ${CMAKE_CURRENT_SOURCE_DIR}/smart_bitmask.edc
${CMAKE_CURRENT_SOURCE_DIR}/synthpod.edc
${CMAKE_CURRENT_SOURCE_DIR}/theme.edc
${CMAKE_CURRENT_SOURCE_DIR}/omk_logo.edc
diff --git a/data/smart_bitmask.edc b/data/smart_bitmask.edc
new file mode 100644
index 00000000..55a77123
--- /dev/null
+++ b/data/smart_bitmask.edc
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#define SMART_BITMASK_UI "/synthpod/smart_bitmask/ui"
+
+group {
+ name: "/synthpod/smart_bitmask/node";
+
+ parts {
+ part {
+ name: "border";
+ type: RECT;
+ mouse_events: 0;
+ description {
+ state: "default" 0.0;
+ color: 48 48 48 255;
+ }
+ description {
+ state: "default" 1.0;
+ inherit: "default" 0.0;
+ color: 255 255 255 255;
+ }
+ }
+
+ part {
+ name: "label";
+ type: TEXT;
+ mouse_events: 0;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ text {
+ size: 10;
+ fit: 1 1;
+ align: 0.5 0.5;
+ text: "";
+ }
+ color: 255 255 255 255;
+ }
+ description {
+ state: "default" 1.0;
+ inherit: "default" 0.0;
+ color: 48 48 48 255;
+ }
+ }
+
+ part {
+ name: "ev";
+ type: RECT;
+ mouse_events: 1;
+ description {
+ state: "default" 0.0;
+ color: 255 255 255 0;
+ }
+ }
+ }
+
+ programs {
+ program {
+ signal: "on";
+ source: SMART_BITMASK_UI;
+ action: STATE_SET "default" 1.0;
+ target: "border";
+ target: "label";
+ }
+ program {
+ signal: "off";
+ source: SMART_BITMASK_UI;
+ action: STATE_SET "default" 0.0;
+ target: "border";
+ target: "label";
+ }
+ }
+}
+
+group {
+ name: "/synthpod/smart_bitmask/theme";
+
+ parts {
+ part {
+ name: "shadow";
+ type: RECT;
+ mouse_events: 0;
+ description {
+ state: "default" 0.0;
+ fixed: 1 1;
+ rel1.relative: 0.0 0.05;
+ rel2.relative: 1.0 0.95;
+ color: 32 32 32 255;
+ }
+ }
+
+ part {
+ name: "col.clip";
+ type: RECT;
+ mouse_events: 0;
+ description { state: "default" 0.00; fixed: 1 1; color: COL00;
+ rel1.to: "shadow";
+ rel2.to: "shadow";
+ }
+ description { state: "default" 0.01; inherit: "default" 0.00; color: COL01; }
+ description { state: "default" 0.02; inherit: "default" 0.00; color: COL02; }
+ description { state: "default" 0.03; inherit: "default" 0.00; color: COL03; }
+ description { state: "default" 0.04; inherit: "default" 0.00; color: COL04; }
+ description { state: "default" 0.05; inherit: "default" 0.00; color: COL05; }
+ description { state: "default" 0.06; inherit: "default" 0.00; color: COL06; }
+ description { state: "default" 0.07; inherit: "default" 0.00; color: COL07; }
+ description { state: "default" 0.08; inherit: "default" 0.00; color: COL08; }
+ description { state: "default" 0.09; inherit: "default" 0.00; color: COL09; }
+ description { state: "default" 0.10; inherit: "default" 0.00; color: COL10; }
+ description { state: "default" 0.11; inherit: "default" 0.00; color: COL11; }
+ description { state: "default" 0.12; inherit: "default" 0.00; color: COL12; }
+ description { state: "default" 0.13; inherit: "default" 0.00; color: COL13; }
+ description { state: "default" 0.14; inherit: "default" 0.00; color: COL14; }
+ description { state: "default" 0.15; inherit: "default" 0.00; color: COL15; }
+ description { state: "default" 0.16; inherit: "default" 0.00; color: COL16; }
+ description { state: "default" 0.17; inherit: "default" 0.00; color: COL17; }
+ description { state: "default" 0.18; inherit: "default" 0.00; color: COL18; }
+ description { state: "default" 0.19; inherit: "default" 0.00; color: COL19; }
+ description { state: "default" 0.20; inherit: "default" 0.00; color: COL20; }
+ }
+
+ part {
+ name: "table";
+ type: TABLE;
+ mouse_events: 1;
+ clip_to: "col.clip";
+ description {
+ state: "default" 0.0;
+ color: 255 255 255 128;
+ table {
+ homogeneous: TABLE;
+ padding: 1 1;
+ align: 0.5 0.5;
+ }
+ }
+ description {
+ state: "default" 1.0;
+ inherit: "default" 0.0;
+ color: 255 255 255 255;
+ }
+ }
+ }
+
+ programs {
+ program { signal: "col,00"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.00; target: "col.clip"; }
+ program { signal: "col,01"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.01; target: "col.clip"; }
+ program { signal: "col,02"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.02; target: "col.clip"; }
+ program { signal: "col,03"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.03; target: "col.clip"; }
+ program { signal: "col,04"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.04; target: "col.clip"; }
+ program { signal: "col,05"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.05; target: "col.clip"; }
+ program { signal: "col,06"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.06; target: "col.clip"; }
+ program { signal: "col,07"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.07; target: "col.clip"; }
+ program { signal: "col,08"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.08; target: "col.clip"; }
+ program { signal: "col,09"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.09; target: "col.clip"; }
+ program { signal: "col,10"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.10; target: "col.clip"; }
+ program { signal: "col,11"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.11; target: "col.clip"; }
+ program { signal: "col,12"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.12; target: "col.clip"; }
+ program { signal: "col,13"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.13; target: "col.clip"; }
+ program { signal: "col,14"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.14; target: "col.clip"; }
+ program { signal: "col,15"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.15; target: "col.clip"; }
+ program { signal: "col,16"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.16; target: "col.clip"; }
+ program { signal: "col,17"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.17; target: "col.clip"; }
+ program { signal: "col,18"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.18; target: "col.clip"; }
+ program { signal: "col,19"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.19; target: "col.clip"; }
+ program { signal: "col,20"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.20; target: "col.clip"; }
+
+ program { signal: "enabled"; source: SMART_BITMASK_UI; action: STATE_SET "default" 1.0; target: "table"; }
+ program { signal: "disabled"; source: SMART_BITMASK_UI; action: STATE_SET "default" 0.0; target: "table"; }
+ }
+}
diff --git a/data/synthpod.edc b/data/synthpod.edc
index 9b6208af..c36ceff5 100644
--- a/data/synthpod.edc
+++ b/data/synthpod.edc
@@ -83,6 +83,7 @@ collections {
#include <smart_meter.edc>
#include <smart_spinner.edc>
#include <smart_toggle.edc>
+#include <smart_bitmask.edc>
#include <entry.edc>
#include <group.edc>
}
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index c4b290a5..08e06f80 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -43,7 +43,8 @@ add_library(synthpod_ui.lib SHARED
smart_slider.c
smart_meter.c
smart_spinner.c
- smart_toggle.c)
+ smart_toggle.c
+ smart_bitmask.c)
target_link_libraries(synthpod_ui.lib
${ELM_LDFLAGS}
${LILV_LDFLAGS}
diff --git a/lib/smart_bitmask.c b/lib/smart_bitmask.c
new file mode 100644
index 00000000..da7ad660
--- /dev/null
+++ b/lib/smart_bitmask.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#include <Edje.h>
+
+#include <smart_bitmask.h>
+
+#define SMART_BITMASK_TYPE "Smart Bitmask"
+
+#define SMART_BITMASK_CHANGED "changed"
+#define SMART_BITMASK_MOUSE_IN "cat,in"
+#define SMART_BITMASK_MOUSE_OUT "cat,out"
+#define MAX_NBITS 64
+
+typedef struct _smart_bitmask_t smart_bitmask_t;
+
+struct _smart_bitmask_t {
+ Evas_Object *theme;
+ Evas_Object *self;
+
+ int nbits;
+ int64_t value;
+ int disabled;
+ Evas_Object *bits [MAX_NBITS];
+};
+
+static const Evas_Smart_Cb_Description _smart_callbacks [] = {
+ {SMART_BITMASK_CHANGED, ""},
+ {SMART_BITMASK_MOUSE_IN, ""},
+ {SMART_BITMASK_MOUSE_OUT, ""},
+ {NULL, NULL}
+};
+
+EVAS_SMART_SUBCLASS_NEW(SMART_BITMASK_TYPE, _smart_bitmask,
+ Evas_Smart_Class, Evas_Smart_Class,
+ evas_object_smart_clipped_class_get, _smart_callbacks);
+
+static inline void
+_smart_bitmask_value_flush(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+
+ for(int i=0; i<priv->nbits; i++)
+ {
+ const int64_t mask = 1 << i;
+ if(priv->value & mask)
+ edje_object_signal_emit(priv->bits[i], "on", SMART_BITMASK_UI);
+ else
+ edje_object_signal_emit(priv->bits[i], "off", SMART_BITMASK_UI);
+ }
+}
+
+static void
+_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ evas_object_smart_callback_call(obj, SMART_BITMASK_MOUSE_IN, NULL);
+}
+
+static void
+_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ evas_object_smart_callback_call(obj, SMART_BITMASK_MOUSE_OUT, NULL);
+}
+
+static void
+_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ smart_bitmask_t *priv = data;
+
+ if(priv->disabled)
+ return;
+
+ int nbit = -1;
+ for(int i=0; i<priv->nbits; i++)
+ if(obj == priv->bits[i])
+ {
+ nbit = i;
+ break;
+ }
+
+ if(nbit == -1)
+ return;
+
+ const int64_t mask = 1 << nbit;
+ if(priv->value & mask)
+ priv->value &= ~mask;
+ else
+ priv->value |= mask;
+
+ _smart_bitmask_value_flush(priv->self);
+ evas_object_smart_callback_call(priv->self, SMART_BITMASK_CHANGED, NULL);
+}
+
+static void
+_mouse_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ smart_bitmask_t *priv = data;
+
+ if(priv->disabled)
+ return;
+
+ int nbit = -1;
+ for(int i=0; i<priv->nbits; i++)
+ if(obj == priv->bits[i])
+ {
+ nbit = i;
+ break;
+ }
+
+ if(nbit == -1)
+ return;
+
+ const int64_t mask = 1 << nbit;
+ if(priv->value & mask)
+ priv->value &= ~mask;
+ else
+ priv->value |= mask;
+
+ _smart_bitmask_value_flush(priv->self);
+ evas_object_smart_callback_call(priv->self, SMART_BITMASK_CHANGED, NULL);
+}
+
+static void
+_smart_bitmask_smart_init(Evas_Object *o)
+{
+ Evas *e = evas_object_evas_get(o);
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+
+ for(int i=0; i<priv->nbits; i++)
+ {
+ Evas_Object *bit = edje_object_add(e);
+ if(bit)
+ {
+ edje_object_file_set(bit, SYNTHPOD_DATA_DIR"/synthpod.edj",
+ "/synthpod/smart_bitmask/node"); //TODO
+ evas_object_size_hint_weight_set(bit, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(bit, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ evas_object_event_callback_add(bit, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, priv);
+ evas_object_event_callback_add(bit, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel, priv);
+
+ const unsigned colmax = 16 - 1;
+ const unsigned rowmax = (priv->nbits - 1) / 16;
+ const unsigned col = i % 16;
+ const unsigned row = i / 16;
+ edje_object_part_table_pack(priv->theme, "table", bit,
+ colmax - col, rowmax - row, 1, 1);
+ /*
+ const unsigned col = i;
+ const unsigned row = 0;
+ edje_object_part_table_pack(priv->theme, "table", bit, priv->nbits - 1 - col, row, 1, 1);
+ */
+
+ char label [16];
+ snprintf(label, 16, "%"PRIu8, i + 1);
+ edje_object_part_text_set(bit, "label", label);
+
+ evas_object_show(bit);
+ }
+
+ priv->bits[i] = bit;
+ }
+}
+
+static void
+_smart_bitmask_smart_deinit(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+
+ for(int i=0; i<priv->nbits; i++)
+ {
+ edje_object_part_table_unpack(priv->theme, "table", priv->bits[i]);
+ evas_object_del(priv->bits[i]);
+ priv->bits[i] = NULL;
+ }
+}
+
+static void
+_smart_bitmask_smart_add(Evas_Object *o)
+{
+ Evas *e = evas_object_evas_get(o);
+ EVAS_SMART_DATA_ALLOC(o, smart_bitmask_t);
+
+ _smart_bitmask_parent_sc->add(o);
+
+ priv->self = o;
+ priv->nbits = 0;
+ priv->value = 0;
+ priv->disabled = 0;
+ for(unsigned i=0; i<MAX_NBITS; i++)
+ priv->bits[i] = NULL;
+
+ priv->theme = edje_object_add(e);
+ edje_object_file_set(priv->theme, SYNTHPOD_DATA_DIR"/synthpod.edj",
+ "/synthpod/smart_bitmask/theme"); //TODO
+ evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN, _mouse_in, priv);
+ evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _mouse_out, priv);
+ evas_object_show(priv->theme);
+ evas_object_smart_member_add(priv->theme, o);
+
+ _smart_bitmask_smart_init(o);
+}
+
+static void
+_smart_bitmask_smart_del(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+
+ _smart_bitmask_smart_deinit(o);
+ _smart_bitmask_parent_sc->del(o);
+}
+
+static void
+_smart_bitmask_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
+{
+ Evas_Coord ow, oh;
+
+ evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
+ if( (ow == w) && (oh == h) )
+ return;
+
+ evas_object_smart_changed(o);
+}
+
+static void
+_smart_bitmask_smart_calculate(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ Evas_Coord x, y, w, h;
+
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ evas_object_resize(priv->theme, w, h);
+ evas_object_move(priv->theme, x, y);
+
+ _smart_bitmask_value_flush(o);
+}
+
+static void
+_smart_bitmask_smart_set_user(Evas_Smart_Class *sc)
+{
+ // function overloading
+ sc->add = _smart_bitmask_smart_add;
+ sc->del = _smart_bitmask_smart_del;
+ sc->resize = _smart_bitmask_smart_resize;
+ sc->calculate = _smart_bitmask_smart_calculate;
+}
+
+Evas_Object *
+smart_bitmask_add(Evas *e)
+{
+ return evas_object_smart_add(e, _smart_bitmask_smart_class_new());
+}
+
+void
+smart_bitmask_value_set(Evas_Object *o, int64_t value)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return;
+
+ priv->value = value;
+
+ _smart_bitmask_value_flush(o);
+}
+
+int64_t
+smart_bitmask_value_get(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return 0;
+
+ return priv->value;
+}
+
+void
+smart_bitmask_bits_set(Evas_Object *o, int nbits)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return;
+
+ if(priv->nbits == nbits)
+ return;
+
+ _smart_bitmask_smart_deinit(o);
+ priv->nbits = nbits;
+ _smart_bitmask_smart_init(o);
+}
+
+int
+smart_bitmask_bits_get(Evas_Object *o)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return 0;
+
+ return priv->nbits;
+}
+
+void
+smart_bitmask_color_set(Evas_Object *o, int col)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return;
+
+ char sig[7];
+ sprintf(sig, "col,%02i", col);
+ edje_object_signal_emit(priv->theme, sig, SMART_BITMASK_UI);
+}
+
+void
+smart_bitmask_disabled_set(Evas_Object *o, int disabled)
+{
+ smart_bitmask_t *priv = evas_object_smart_data_get(o);
+ if(!priv)
+ return;
+
+ priv->disabled = disabled;
+
+ if(priv->disabled)
+ edje_object_signal_emit(priv->theme, "disabled", SMART_BITMASK_UI);
+ else
+ edje_object_signal_emit(priv->theme, "enabled", SMART_BITMASK_UI);
+}
diff --git a/lib/smart_bitmask.h b/lib/smart_bitmask.h
new file mode 100644
index 00000000..36ac76cc
--- /dev/null
+++ b/lib/smart_bitmask.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _SYNTHPOD_SMART_BITMASK_H
+#define _SYNTHPOD_SMART_BITMASK_H
+
+#include <Evas.h>
+
+#define SMART_BITMASK_UI "/synthpod/smart_bitmask/ui"
+
+Evas_Object *
+smart_bitmask_add(Evas *e);
+
+void
+smart_bitmask_value_set(Evas_Object *o, int64_t value);
+int64_t
+smart_bitmask_value_get(Evas_Object *o);
+
+void
+smart_bitmask_bits_set(Evas_Object *o, int nbits);
+int
+smart_bitmask_bits_get(Evas_Object *o);
+
+void
+smart_bitmask_color_set(Evas_Object *o, int col);
+
+void
+smart_bitmask_disabled_set(Evas_Object *o, int disabled);
+
+#endif // _SYNTHPOD_SMART_BITMASK_H
diff --git a/lib/smart_meter.c b/lib/smart_meter.c
index d3fe9eb6..744fed36 100644
--- a/lib/smart_meter.c
+++ b/lib/smart_meter.c
@@ -19,7 +19,7 @@
#include <smart_meter.h>
-#define SMART_METER_TYPE "Smart Slider"
+#define SMART_METER_TYPE "Smart Meter"
typedef struct _smart_meter_t smart_meter_t;
diff --git a/lib/smart_spinner.c b/lib/smart_spinner.c
index 9fe19c98..4608fd4e 100644
--- a/lib/smart_spinner.c
+++ b/lib/smart_spinner.c
@@ -19,7 +19,7 @@
#include <smart_spinner.h>
-#define SMART_SPINNER_TYPE "Smart Slider"
+#define SMART_SPINNER_TYPE "Smart Spinner"
#define SMART_SPINNER_CHANGED "changed"
#define SMART_SPINNER_MOUSE_IN "cat,in"
diff --git a/lib/smart_toggle.c b/lib/smart_toggle.c
index e7a82389..86bba86e 100644
--- a/lib/smart_toggle.c
+++ b/lib/smart_toggle.c
@@ -19,7 +19,7 @@
#include <smart_toggle.h>
-#define SMART_TOGGLE_TYPE "Smart Slider"
+#define SMART_TOGGLE_TYPE "Smart Toggle"
#define SMART_TOGGLE_CHANGED "changed"
#define SMART_TOGGLE_MOUSE_IN "cat,in"
diff --git a/lib/synthpod_private.h b/lib/synthpod_private.h
index b2cdbcff..9af6e59b 100644
--- a/lib/synthpod_private.h
+++ b/lib/synthpod_private.h
@@ -132,6 +132,7 @@ struct _reg_t {
reg_item_t integer;
reg_item_t enumeration;
reg_item_t toggled;
+ reg_item_t is_bitmask;
// port protocols
reg_item_t float_protocol;
@@ -147,6 +148,10 @@ struct _reg_t {
} port;
struct {
+ reg_item_t property;
+ } parameter;
+
+ struct {
reg_item_t schedule;
} work;
@@ -369,6 +374,7 @@ sp_regs_init(reg_t *regs, LilvWorld *world, LV2_URID_Map *map)
_register(&regs->port.integer, world, map, LV2_CORE__integer);
_register(&regs->port.enumeration, world, map, LV2_CORE__enumeration);
_register(&regs->port.toggled, world, map, LV2_CORE__toggled);
+ _register(&regs->port.is_bitmask, world, map, LV2_CORE_PREFIX"isBitmask");
_register(&regs->port.float_protocol, world, map, LV2_UI_PREFIX"floatProtocol");
_register(&regs->port.peak_protocol, world, map, LV2_UI_PREFIX"peakProtocol");
@@ -380,6 +386,8 @@ sp_regs_init(reg_t *regs, LilvWorld *world, LV2_URID_Map *map)
_register(&regs->port.logarithmic, world, map, LV2_PORT_PROPS__logarithmic);
+ _register(&regs->parameter.property, world, map, LV2_CORE_PREFIX"parameterProperty");
+
_register(&regs->work.schedule, world, map, LV2_WORKER__schedule);
_register(&regs->zero.schedule, world, map, ZERO_WORKER__schedule);
@@ -551,6 +559,7 @@ sp_regs_deinit(reg_t *regs)
_unregister(&regs->port.integer);
_unregister(&regs->port.enumeration);
_unregister(&regs->port.toggled);
+ _unregister(&regs->port.is_bitmask);
_unregister(&regs->port.float_protocol);
_unregister(&regs->port.peak_protocol);
@@ -562,6 +571,8 @@ sp_regs_deinit(reg_t *regs)
_unregister(&regs->port.logarithmic);
+ _unregister(&regs->parameter.property);
+
_unregister(&regs->work.schedule);
_unregister(&regs->zero.schedule);
diff --git a/lib/synthpod_ui.c b/lib/synthpod_ui.c
index cce2b21f..253bf120 100644
--- a/lib/synthpod_ui.c
+++ b/lib/synthpod_ui.c
@@ -25,6 +25,7 @@
#include <smart_meter.h>
#include <smart_spinner.h>
#include <smart_toggle.h>
+#include <smart_bitmask.h>
#include <lv2_external_ui.h> // kxstudio kx-ui extension
#include <zero_writer.h>
@@ -236,6 +237,7 @@ struct _port_t {
bool integer;
bool toggled;
+ bool is_bitmask;
bool logarithmic;
LilvScalePoints *points;
char *unit;
@@ -269,6 +271,7 @@ struct _property_t {
char *comment;
LV2_URID tar_urid;
LV2_URID type_urid;
+ bool is_bitmask;
struct {
Elm_Object_Item *elmnt;
@@ -621,7 +624,10 @@ _mod_set_property(mod_t *mod, LV2_URID property_val, const LV2_Atom *value)
else if(prop->type_urid == ui->forge.Int)
{
int32_t val = ((const LV2_Atom_Int *)value)->body;
- smart_slider_value_set(prop->std.widget, val);
+ if(prop->is_bitmask)
+ smart_bitmask_value_set(prop->std.widget, val);
+ else
+ smart_slider_value_set(prop->std.widget, val);
}
else if(prop->type_urid == ui->forge.URID)
{
@@ -631,7 +637,10 @@ _mod_set_property(mod_t *mod, LV2_URID property_val, const LV2_Atom *value)
else if(prop->type_urid == ui->forge.Long)
{
int64_t val = ((const LV2_Atom_Long *)value)->body;
- smart_slider_value_set(prop->std.widget, val);
+ if(prop->is_bitmask)
+ smart_bitmask_value_set(prop->std.widget, val);
+ else
+ smart_slider_value_set(prop->std.widget, val);
}
else if(prop->type_urid == ui->forge.Float)
{
@@ -787,6 +796,8 @@ _std_port_event(LV2UI_Handle handle, uint32_t index, uint32_t size,
{
if(port->toggled)
smart_toggle_value_set(port->std.widget, floor(val));
+ else if(port->is_bitmask)
+ smart_bitmask_value_set(port->std.widget, floor(val));
else if(port->points)
smart_spinner_value_set(port->std.widget, val);
else // integer or float
@@ -1029,6 +1040,7 @@ _std_port_event(LV2UI_Handle handle, uint32_t index, uint32_t size,
{
prop->mod = mod;
prop->editable = 0;
+ prop->is_bitmask = false;
prop->tar_urid = ((const LV2_Atom_URID *)&atom_prop->value)->body;
prop->label = NULL; // not yet known
prop->comment = NULL; // not yet known
@@ -1069,6 +1081,7 @@ _std_port_event(LV2UI_Handle handle, uint32_t index, uint32_t size,
{
prop->mod = mod;
prop->editable = 1;
+ prop->is_bitmask = false;
prop->tar_urid = ((const LV2_Atom_URID *)&atom_prop->value)->body;
prop->label = NULL; // not yet known
prop->comment = NULL; // not yet known
@@ -2577,6 +2590,7 @@ _sp_ui_mod_port_add(sp_ui_t *ui, mod_t *mod, uint32_t i, port_t *tar, const Lilv
tar->integer = lilv_port_has_property(mod->plug, tar->tar, ui->regs.port.integer.node);
tar->toggled = lilv_port_has_property(mod->plug, tar->tar, ui->regs.port.toggled.node);
+ tar->is_bitmask = lilv_port_has_property(mod->plug, tar->tar, ui->regs.port.is_bitmask.node);
tar->logarithmic = lilv_port_has_property(mod->plug, tar->tar, ui->regs.port.logarithmic.node);
int enumeration = lilv_port_has_property(mod->plug, port, ui->regs.port.enumeration.node);
tar->points = enumeration
@@ -2656,6 +2670,7 @@ _sp_ui_mod_static_prop_add(sp_ui_t *ui, mod_t *mod, const LilvNode *writable, in
prop->mod = mod;
prop->editable = editable;
+ prop->is_bitmask = false;
prop->label = NULL;
prop->comment = NULL;
prop->tar_urid = ui->driver->map->map(ui->driver->map->handle, writable_str);
@@ -2663,6 +2678,15 @@ _sp_ui_mod_static_prop_add(sp_ui_t *ui, mod_t *mod, const LilvNode *writable, in
prop->minimum = 0.f; // not yet known
prop->maximum = 1.f; // not yet known
prop->unit = NULL; // not yet known
+
+ // get lv2:parameterProperty
+ LilvNode *paramprop = lilv_world_get(ui->world, writable,
+ ui->regs.rdfs.label.node, NULL);
+ if(paramprop)
+ {
+ prop->is_bitmask = true; //FIXME
+ lilv_node_free(paramprop);
+ }
// get rdfs:label
LilvNode *label = lilv_world_get(ui->world, writable,
@@ -4458,6 +4482,64 @@ _property_sldr_changed(void *data, Evas_Object *obj, void *event_info)
}
static void
+_property_bitmask_changed(void *data, Evas_Object *obj, void *event_info)
+{
+ property_t *prop = data;
+ mod_t *mod = prop->mod;
+ sp_ui_t *ui = mod->ui;
+
+ int64_t value = smart_bitmask_value_get(obj);
+
+ size_t body_size = 0;
+ if(prop->type_urid == ui->forge.Int)
+ body_size = sizeof(int32_t);
+ else if(prop->type_urid == ui->forge.Long)
+ body_size = sizeof(int64_t);
+ else
+ return; // unsupported type
+
+ size_t len = sizeof(transfer_patch_set_obj_t) + lv2_atom_pad_size(body_size);
+
+ for(unsigned index=0; index<mod->num_ports; index++)
+ {
+ port_t *port = &mod->ports[index];
+
+ // only consider event ports which support patch:Message
+ if( (port->buffer_type != PORT_BUFFER_TYPE_SEQUENCE)
+ || (port->direction != PORT_DIRECTION_INPUT)
+ || !port->patchable)
+ {
+ continue; // skip
+ }
+
+ transfer_patch_set_obj_t *trans = malloc(len);
+ if(trans)
+ {
+ LV2_Atom *atom = _sp_transfer_patch_set_obj_fill(&ui->regs,
+ &ui->forge, trans, body_size,
+ mod->subject, prop->tar_urid, prop->type_urid);
+ if(atom)
+ {
+ if(prop->type_urid == ui->forge.Int)
+ ((LV2_Atom_Int *)atom)->body = value;
+ else if(prop->type_urid == ui->forge.Long)
+ ((LV2_Atom_Long *)atom)->body = value;
+ else if(prop->type_urid == ui->forge.Float)
+ ((LV2_Atom_Float *)atom)->body = value;
+ else if(prop->type_urid == ui->forge.Double)
+ ((LV2_Atom_Double *)atom)->body = value;
+ else if(prop->type_urid == ui->forge.URID)
+ ((LV2_Atom_URID *)atom)->body = value;
+
+ _std_ui_write_function(mod, index, lv2_atom_total_size(&trans->obj.atom),
+ ui->regs.port.event_transfer.urid, &trans->obj);
+ }
+ free(trans);
+ }
+ }
+}
+
+static void
_property_check_changed(void *data, Evas_Object *obj, void *event_info)
{
property_t *prop = data;
@@ -4678,28 +4760,46 @@ _property_content_get(void *data, Evas_Object *obj, const char *part)
|| (prop->type_urid == ui->forge.Float)
|| (prop->type_urid == ui->forge.Double) )
{
- child = smart_slider_add(evas_object_evas_get(lay));
- if(child)
+ if(prop->is_bitmask)
{
- int integer = (prop->type_urid == ui->forge.Int)
- || (prop->type_urid == ui->forge.URID)
- || (prop->type_urid == ui->forge.Long);
- double min = prop->minimum;
- double max = prop->maximum;
- double dflt = prop->minimum; //FIXME
-
- smart_slider_range_set(child, min, max, dflt);
- smart_slider_color_set(child, mod->col);
- smart_slider_integer_set(child, integer);
- //smart_slider_logarithmic_set(child, logarithmic); //TODO
- smart_slider_format_set(child, integer ? "%.0f %s" : "%.4f %s"); //TODO handle MIDI notes
- smart_slider_disabled_set(child, !prop->editable);
- if(prop->unit)
- smart_slider_unit_set(child, prop->unit);
- if(prop->editable)
- evas_object_smart_callback_add(child, "changed", _property_sldr_changed, prop);
- evas_object_smart_callback_add(child, "cat,in", _smart_mouse_in, mod);
- evas_object_smart_callback_add(child, "cat,out", _smart_mouse_out, mod);
+ child = smart_bitmask_add(evas_object_evas_get(lay));
+ if(child)
+ {
+ smart_bitmask_color_set(child, mod->col);
+ smart_bitmask_disabled_set(child, !prop->editable);
+ const int nbits = log2(prop->maximum + 1);
+ smart_bitmask_bits_set(child, nbits);
+ if(prop->editable)
+ evas_object_smart_callback_add(child, "changed", _property_bitmask_changed, prop);
+ evas_object_smart_callback_add(child, "cat,in", _smart_mouse_in, mod);
+ evas_object_smart_callback_add(child, "cat,out", _smart_mouse_out, mod);
+ }
+ }
+ else // !is_bitmask
+ {
+ child = smart_slider_add(evas_object_evas_get(lay));
+ if(child)
+ {
+ int integer = (prop->type_urid == ui->forge.Int)
+ || (prop->type_urid == ui->forge.URID)
+ || (prop->type_urid == ui->forge.Long);
+ double min = prop->minimum;
+ double max = prop->maximum;
+ double dflt = prop->minimum; //FIXME
+
+ smart_slider_range_set(child, min, max, dflt);
+ smart_slider_color_set(child, mod->col);
+ smart_slider_integer_set(child, integer);
+ //smart_slider_logarithmic_set(child, logarithmic); //TODO
+ smart_slider_format_set(child, integer ? "%.0f %s" : "%.4f %s"); //TODO handle MIDI notes
+ smart_slider_disabled_set(child, !prop->editable);
+ if(prop->unit)
+ smart_slider_unit_set(child, prop->unit);
+ if(prop->editable)
+ evas_object_smart_callback_add(child, "changed", _property_sldr_changed, prop);
+ evas_object_smart_callback_add(child, "cat,in", _smart_mouse_in, mod);
+ evas_object_smart_callback_add(child, "cat,out", _smart_mouse_out, mod);
+ }
}
}
else if(prop->type_urid == ui->forge.Bool)
@@ -4918,6 +5018,19 @@ _check_changed(void *data, Evas_Object *obj, void *event)
}
static void
+_bitmask_changed(void *data, Evas_Object *obj, void *event)
+{
+ port_t *port = data;
+ mod_t *mod = port->mod;
+ sp_ui_t *ui = mod->ui;
+
+ float val = smart_bitmask_value_get(obj);
+
+ _std_ui_write_function(mod, port->index, sizeof(float),
+ ui->regs.port.float_protocol.urid, &val);
+}
+
+static void
_spinner_changed(void *data, Evas_Object *obj, void *event)
{
port_t *port = data;
@@ -5050,6 +5163,23 @@ _modlist_std_content_get(void *data, Evas_Object *obj, const char *part)
child = check;
}
+ if(port->is_bitmask)
+ {
+ Evas_Object *bitmask = smart_bitmask_add(evas_object_evas_get(lay));
+ if(bitmask)
+ {
+ smart_bitmask_color_set(bitmask, mod->col);
+ smart_bitmask_disabled_set(bitmask, port->direction == PORT_DIRECTION_OUTPUT);
+ const int nbits = log2(port->max + 1);
+ smart_bitmask_bits_set(bitmask, nbits);
+ if(port->direction == PORT_DIRECTION_INPUT)
+ evas_object_smart_callback_add(bitmask, "changed", _bitmask_changed, port);
+ evas_object_smart_callback_add(bitmask, "cat,in", _smart_mouse_in, mod);
+ evas_object_smart_callback_add(bitmask, "cat,out", _smart_mouse_out, mod);
+ }
+
+ child = bitmask;
+ }
else if(port->points)
{
Evas_Object *spin = smart_spinner_add(evas_object_evas_get(lay));