diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2016-03-18 16:51:40 +0100 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2016-03-18 16:51:40 +0100 |
commit | 800333f0714c6197f6b2a6ada6460f56e54ccbfe (patch) | |
tree | ffeddd396c5b302d3b637b2b475d4e8a563d66e8 | |
parent | e39c06bbd0c798a51533db3ac89c957ae205c8cc (diff) | |
download | synthpod-800333f0714c6197f6b2a6ada6460f56e54ccbfe.tar.xz |
prototype bitmask port/parameter property widget.
-rw-r--r-- | data/CMakeLists.txt | 1 | ||||
-rw-r--r-- | data/smart_bitmask.edc | 185 | ||||
-rw-r--r-- | data/synthpod.edc | 1 | ||||
-rw-r--r-- | lib/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/smart_bitmask.c | 341 | ||||
-rw-r--r-- | lib/smart_bitmask.h | 44 | ||||
-rw-r--r-- | lib/smart_meter.c | 2 | ||||
-rw-r--r-- | lib/smart_spinner.c | 2 | ||||
-rw-r--r-- | lib/smart_toggle.c | 2 | ||||
-rw-r--r-- | lib/synthpod_private.h | 11 | ||||
-rw-r--r-- | lib/synthpod_ui.c | 176 |
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(®s->port.integer, world, map, LV2_CORE__integer); _register(®s->port.enumeration, world, map, LV2_CORE__enumeration); _register(®s->port.toggled, world, map, LV2_CORE__toggled); + _register(®s->port.is_bitmask, world, map, LV2_CORE_PREFIX"isBitmask"); _register(®s->port.float_protocol, world, map, LV2_UI_PREFIX"floatProtocol"); _register(®s->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(®s->port.logarithmic, world, map, LV2_PORT_PROPS__logarithmic); + _register(®s->parameter.property, world, map, LV2_CORE_PREFIX"parameterProperty"); + _register(®s->work.schedule, world, map, LV2_WORKER__schedule); _register(®s->zero.schedule, world, map, ZERO_WORKER__schedule); @@ -551,6 +559,7 @@ sp_regs_deinit(reg_t *regs) _unregister(®s->port.integer); _unregister(®s->port.enumeration); _unregister(®s->port.toggled); + _unregister(®s->port.is_bitmask); _unregister(®s->port.float_protocol); _unregister(®s->port.peak_protocol); @@ -562,6 +571,8 @@ sp_regs_deinit(reg_t *regs) _unregister(®s->port.logarithmic); + _unregister(®s->parameter.property); + _unregister(®s->work.schedule); _unregister(®s->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)); |