diff --git a/ceammc/ext/doc/an.onset~-help.pd b/ceammc/ext/doc/an.onset~-help.pd
index 785c0a074e..55b69ca63f 100644
--- a/ceammc/ext/doc/an.onset~-help.pd
+++ b/ceammc/ext/doc/an.onset~-help.pd
@@ -59,8 +59,8 @@ value: 1\.;
#X msg 110 696 @complex;
#X text 245 696 Alias to @method complex. Complex Domain Method onset
detection function.;
-#X msg 110 738 @compression;
-#X text 245 738 Get/Set lambda logarithmic compression factor \, 0
+#X msg 110 753 @compression;
+#X text 245 753 Get/Set lambda logarithmic compression factor \, 0
to disable. Type: float. Default value: 1\. Min value: 0\.;
#X msg 110 780 @delay;
#X text 245 780 Get/Set constant system delay to take back from detection
diff --git a/ceammc/ext/doc/canvas.dir.abs0.pd b/ceammc/ext/doc/canvas.dir.abs0.pd
new file mode 100644
index 0000000000..6816d1460c
--- /dev/null
+++ b/ceammc/ext/doc/canvas.dir.abs0.pd
@@ -0,0 +1,9 @@
+#N canvas 0 0 365 241 12;
+#X obj 20 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 20 77 canvas.dir.sp0;
+#X obj 20 106 ui.dt @auto_size 0 @size 400 45;
+#X floatatom 96 164 5 0 0 0 - - -;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
diff --git a/ceammc/ext/doc/canvas.dir.abs1.pd b/ceammc/ext/doc/canvas.dir.abs1.pd
new file mode 100644
index 0000000000..28a26d2133
--- /dev/null
+++ b/ceammc/ext/doc/canvas.dir.abs1.pd
@@ -0,0 +1,9 @@
+#N canvas 0 0 365 241 12;
+#X obj 20 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 20 77 canvas.dir @abs 0;
+#X obj 20 106 ui.dt @auto_size 0 @size 400 45;
+#X floatatom 96 164 5 0 0 0 - - -;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
diff --git a/ceammc/ext/doc/canvas.dir.sp0.pd b/ceammc/ext/doc/canvas.dir.sp0.pd
new file mode 100644
index 0000000000..fce332952f
--- /dev/null
+++ b/ceammc/ext/doc/canvas.dir.sp0.pd
@@ -0,0 +1,8 @@
+#N canvas 0 0 365 241 12;
+#X obj 20 48 inlet;
+#X obj 20 77 canvas.dir @abs 0;
+#X obj 20 106 outlet;
+#X obj 116 106 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
diff --git a/ceammc/ext/doc/canvas.dir.sp1.pd b/ceammc/ext/doc/canvas.dir.sp1.pd
new file mode 100644
index 0000000000..3e08288cfe
--- /dev/null
+++ b/ceammc/ext/doc/canvas.dir.sp1.pd
@@ -0,0 +1,8 @@
+#N canvas 0 0 365 241 12;
+#X obj 20 48 inlet;
+#X obj 20 77 canvas.dir @abs 1;
+#X obj 20 106 outlet;
+#X obj 116 106 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
diff --git a/ceammc/ext/doc/canvas.top.abs.pd b/ceammc/ext/doc/canvas.top.abs.pd
new file mode 100644
index 0000000000..5175583edf
--- /dev/null
+++ b/ceammc/ext/doc/canvas.top.abs.pd
@@ -0,0 +1,11 @@
+#N canvas 0 0 471 241 12;
+#X msg 20 48 bang;
+#X msg 298 48 bang;
+#X obj 20 77 canvas.top.abs0;
+#X obj 298 77 canvas.top.abs1;
+#X obj 20 106 ui.dt;
+#X obj 298 106 ui.dt;
+#X connect 0 0 2 0;
+#X connect 1 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 5 0;
diff --git a/ceammc/ext/doc/canvas.top.abs0.pd b/ceammc/ext/doc/canvas.top.abs0.pd
new file mode 100644
index 0000000000..0c93187217
--- /dev/null
+++ b/ceammc/ext/doc/canvas.top.abs0.pd
@@ -0,0 +1,6 @@
+#N canvas 0 0 471 241 12;
+#X obj 20 48 inlet;
+#X obj 20 77 canvas.top @abs 0;
+#X obj 20 106 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
diff --git a/ceammc/ext/doc/canvas.top.abs1.pd b/ceammc/ext/doc/canvas.top.abs1.pd
new file mode 100644
index 0000000000..271fb1ac37
--- /dev/null
+++ b/ceammc/ext/doc/canvas.top.abs1.pd
@@ -0,0 +1,6 @@
+#N canvas 0 0 471 241 12;
+#X obj 20 48 inlet;
+#X obj 20 77 canvas.top @abs 1;
+#X obj 20 106 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
diff --git a/ceammc/ext/doc/ceammc_lib.xml b/ceammc/ext/doc/ceammc_lib.xml
index 2f98ffab3d..8acb2c4808 100644
--- a/ceammc/ext/doc/ceammc_lib.xml
+++ b/ceammc/ext/doc/ceammc_lib.xml
@@ -1746,6 +1746,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -2621,6 +2632,7 @@
Pierre Guillot
Richard Dudas
Romain Michon
+ Serge Poltavski
Serge Poltavsky
Thomas Le Meur
Till Bovermann
diff --git a/ceammc/ext/doc/dyn.comp_peak~.plot.pd b/ceammc/ext/doc/dyn.comp_peak~.plot.pd
new file mode 100644
index 0000000000..9900f4790c
--- /dev/null
+++ b/ceammc/ext/doc/dyn.comp_peak~.plot.pd
@@ -0,0 +1,22 @@
+#N canvas 0 0 829 614 12;
+#X obj 20 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 20 77 plot.linspace~ -60 6 1024;
+#X obj 327 77 ui.k @show_value 1 @label STRENGTH;
+#X obj 432 77 ui.hsl 0 24 @show_value 1;
+#X obj 20 106 dbfs->amp~;
+#X msg 432 106 @knee \$1;
+#X obj 20 135 dyn.comp_peak~ 1 -20 0.1 1;
+#X obj 20 164 amp->dbfs~;
+#X obj 20 192 ui.plot~ @ymin -60 @ymax 6 @size 400 350 @xlabels 1
+@ylabels 1 @xmin_grid 0 @ymin_ticks 0 @xmin_ticks 0;
+#X text 20 567 ...;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 3 0 5 0;
+#X connect 4 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 1 1 8 1;
+#X connect 2 0 6 1;
+#X connect 5 0 6 0;
diff --git a/ceammc/ext/doc/fluid~-tune-12.pd b/ceammc/ext/doc/fluid~-tune-12.pd
index a2218018a4..cd21c12601 100644
--- a/ceammc/ext/doc/fluid~-tune-12.pd
+++ b/ceammc/ext/doc/fluid~-tune-12.pd
@@ -20,6 +20,9 @@
#X connect 7 0 9 0;
#X connect 8 0 9 0;
#X connect 9 0 11 0;
-#X connect 9 1 11 1;
+#X connect 10 0 11 0;
#X connect 11 0 13 0;
#X connect 11 1 13 1;
+#X connect 13 0 15 0;
+#X connect 13 1 15 1;
+#X connect 2 0 11 0;
diff --git a/ceammc/ext/doc/global.bimap.sp.pd b/ceammc/ext/doc/global.bimap.sp.pd
new file mode 100644
index 0000000000..a03eeb0666
--- /dev/null
+++ b/ceammc/ext/doc/global.bimap.sp.pd
@@ -0,0 +1,15 @@
+#N canvas 0 0 407 241 12;
+#X msg 20 48 1;
+#X msg 58 48 1 3 5;
+#X msg 135 48 2;
+#X msg 173 48 2 4 6;
+#X obj 20 77 global.bimap GBM;
+#X text 212 77 click to view/edit;
+#X obj 20 106 ui.dt;
+#X obj 144 106 ui.dt;
+#X connect 0 0 4 0;
+#X connect 1 0 4 0;
+#X connect 2 0 4 1;
+#X connect 3 0 4 1;
+#X connect 4 0 6 0;
+#X connect 4 1 7 0;
diff --git a/ceammc/ext/doc/patch.args-ex1.pd b/ceammc/ext/doc/patch.args-ex1.pd
index df3e664c9b..e721c79fc4 100644
--- a/ceammc/ext/doc/patch.args-ex1.pd
+++ b/ceammc/ext/doc/patch.args-ex1.pd
@@ -2,5 +2,7 @@
#X obj 20 48 inlet;
#X obj 20 77 patch.args;
#X obj 20 106 outlet;
+#X obj 116 106 outlet;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
+#X connect 1 1 3 0;
diff --git a/ceammc/ext/doc/proto.midi.casio.chorus.pd b/ceammc/ext/doc/proto.midi.casio.chorus.pd
new file mode 100644
index 0000000000..0b3ec31eb4
--- /dev/null
+++ b/ceammc/ext/doc/proto.midi.casio.chorus.pd
@@ -0,0 +1,16 @@
+#N canvas 0 0 533 328 12;
+#X obj 20 48 ui.hrd 5;
+#X obj 192 48 ui.knob;
+#X msg 20 92 chorus_type \$1;
+#X msg 192 92 chorus_depth \$1;
+#X obj 39 120 ui.hsl @show_value 1;
+#X msg 39 149 chorus \$1;
+#X obj 20 178 proto.midi.casio;
+#X obj 20 207 midiout;
+#X connect 0 0 2 0;
+#X connect 1 0 3 0;
+#X connect 4 0 5 0;
+#X connect 2 0 6 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 3 0 6 0;
diff --git a/ceammc/ext/doc/proto.midi.casio.rev.pd b/ceammc/ext/doc/proto.midi.casio.rev.pd
new file mode 100644
index 0000000000..db87bf4905
--- /dev/null
+++ b/ceammc/ext/doc/proto.midi.casio.rev.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 533 328 12;
+#X obj 20 48 ui.hrd 5;
+#X obj 164 48 ui.knob;
+#X msg 20 92 rev_type \$1;
+#X msg 164 92 rev_time \$1;
+#X obj 20 149 proto.midi.casio;
+#X obj 20 178 midiout;
+#X connect 0 0 2 0;
+#X connect 1 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
diff --git a/ceammc/ext/doc/rhythm.hexbeat.list.pd b/ceammc/ext/doc/rhythm.hexbeat.list.pd
new file mode 100644
index 0000000000..9208335b40
--- /dev/null
+++ b/ceammc/ext/doc/rhythm.hexbeat.list.pd
@@ -0,0 +1,8 @@
+#N canvas 0 0 640 328 12;
+#X msg 20 48 list #1 #2 #4 #8;
+#X obj 20 77 rhythm.hexbeat;
+#X obj 20 106 msg set row;
+#X obj 20 135 ui.matrix 4 4;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
diff --git a/ceammc/ext/doc/seq.nbangs.accel.pd b/ceammc/ext/doc/seq.nbangs.accel.pd
new file mode 100644
index 0000000000..79641de8ab
--- /dev/null
+++ b/ceammc/ext/doc/seq.nbangs.accel.pd
@@ -0,0 +1,21 @@
+#N canvas 0 0 414 328 12;
+#X msg 20 48 17;
+#X obj 68 48 ui.k 0.25 4 @show_value 1;
+#X obj 183 48 ui.k -8 8 @show_value 1;
+#X msg 68 106 @accel \$1;
+#X msg 183 106 @curve \$1;
+#X obj 20 135 seq.nbangs @t 200;
+#X obj 20 164 click~;
+#X obj 20 192 flt.resonbp~ 1000 40;
+#X obj 20 221 ui.hgain~;
+#X obj 20 250 dac~;
+#X connect 1 0 3 0;
+#X connect 2 0 4 0;
+#X connect 0 0 5 0;
+#X connect 3 0 5 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 8 0 9 1;
diff --git a/ceammc/ext/doc/snd.play~.resamp.pd b/ceammc/ext/doc/snd.play~.resamp.pd
new file mode 100644
index 0000000000..dba4e07707
--- /dev/null
+++ b/ceammc/ext/doc/snd.play~.resamp.pd
@@ -0,0 +1,22 @@
+#N canvas 0 0 616 472 12;
+#X text 20 48 change in Audio Preferences samplerate \, then play both
+variants;
+#X msg 20 92 symbol %CEAMMC%/guitar1.wav \, 1;
+#X msg 231 120 open %CEAMMC%/guitar1.wav \, 1;
+#X obj 20 178 expand_env;
+#X obj 231 178 expand_env;
+#X obj 20 207 snd.play~ 1;
+#X obj 231 207 readsf~;
+#X obj 20 235 ui.hgain2~;
+#X obj 240 235 ui.dsp~;
+#X obj 20 264 dac~;
+#X connect 1 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 5 0;
+#X connect 4 0 6 0;
+#X connect 5 0 7 0;
+#X connect 5 0 7 1;
+#X connect 6 0 7 0;
+#X connect 6 0 7 1;
+#X connect 7 0 9 0;
+#X connect 7 1 9 1;
diff --git a/ceammc/ext/doc/snd.play~.seek.pd b/ceammc/ext/doc/snd.play~.seek.pd
new file mode 100644
index 0000000000..f15e61a92a
--- /dev/null
+++ b/ceammc/ext/doc/snd.play~.seek.pd
@@ -0,0 +1,27 @@
+#N canvas 0 0 616 472 12;
+#X msg 20 48 symbol %CEAMMC%/guitar1.wav \, 1;
+#X obj 279 48 msg.onclose bang;
+#X obj 20 77 expand_env;
+#X msg 144 77 seek 500;
+#X msg 279 77 stop;
+#X msg 39 106 seek;
+#X msg 144 106 seek 500ms;
+#X msg 279 106 seek 1.5sec;
+#X msg 413 106 seek 15000samp;
+#X obj 20 164 snd.play~ 1 @loop 1;
+#X obj 20 192 ui.hgain2~;
+#X obj 240 192 ui.dsp~;
+#X obj 20 221 dac~;
+#X connect 0 0 2 0;
+#X connect 1 0 4 0;
+#X connect 2 0 9 0;
+#X connect 5 0 9 0;
+#X connect 6 0 9 0;
+#X connect 7 0 9 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 0 10 1;
+#X connect 10 0 12 0;
+#X connect 10 1 12 1;
+#X connect 3 0 9 0;
+#X connect 4 0 9 0;
diff --git a/ceammc/ext/doc/speech.rhvoice~.extra.pd b/ceammc/ext/doc/speech.rhvoice~.extra.pd
new file mode 100644
index 0000000000..f7e9da743e
--- /dev/null
+++ b/ceammc/ext/doc/speech.rhvoice~.extra.pd
@@ -0,0 +1,23 @@
+#N canvas 0 0 739 357 12;
+#X msg 20 48 ssml Я Павела я Анна;
+#X msg 423 77 all;
+#X msg 480 77 !;
+#X msg 48 106 list з+амок и зам+ок;
+#X obj 423 106 symbol;
+#X msg 509 106 symbol;
+#X msg 77 135 list казнить нельзя\ \, помиловать!;
+#X msg 423 135 @punct \$1;
+#X obj 20 164 speech.rhvoice~;
+#X obj 20 192 ui.hgain~;
+#X obj 20 221 dac~;
+#X connect 1 0 4 0;
+#X connect 2 0 4 0;
+#X connect 4 0 7 0;
+#X connect 5 0 7 0;
+#X connect 0 0 8 0;
+#X connect 3 0 8 0;
+#X connect 6 0 8 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 0 10 1;
diff --git a/ceammc/ext/doc/ui.canvas.arrows.pd b/ceammc/ext/doc/ui.canvas.arrows.pd
new file mode 100644
index 0000000000..1ec600137b
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.arrows.pd
@@ -0,0 +1,14 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 width 1 \, arrow 30 30 130 160 A a \, stroke red \, update;
+#X msg 20 77 arrow 60 30 160 160 O o \, stroke blue \, update;
+#X msg 20 106 arrow 90 30 190 160 T t \, stroke navy \, update;
+#X msg 20 135 arrow 120 30 220 160 V v \, stroke orange \, update;
+#X msg 20 164 arrow 150 30 250 160 X x \, stroke gray \, update;
+#X msg 20 192 arrow 180 30 280 160 n n \, stroke green \, update;
+#X obj 20 235 ui.canvas @size 300 200;
+#X connect 0 0 6 0;
+#X connect 1 0 6 0;
+#X connect 2 0 6 0;
+#X connect 3 0 6 0;
+#X connect 4 0 6 0;
+#X connect 5 0 6 0;
diff --git a/ceammc/ext/doc/ui.canvas.color.pd b/ceammc/ext/doc/ui.canvas.color.pd
new file mode 100644
index 0000000000..a966ede37b
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.color.pd
@@ -0,0 +1,26 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 clear \, bg #FFAAFF \, update;
+#X text 327 48 RGB;
+#X msg 20 77 bg #DDAA33AA \, update;
+#X text 327 77 RGBA;
+#X msg 20 106 bg #BEF \, update;
+#X text 327 106 short RGB;
+#X msg 20 135 bg #30D5 \, update;
+#X text 327 135 short RGBA;
+#X msg 20 164 bg navy \, update;
+#X text 327 164 named color;
+#X msg 20 192 bg navy!+50 \, update;
+#X text 327 192 lighter named color;
+#X msg 20 221 bg gray!-50 \, update;
+#X text 327 221 darker named color;
+#X msg 20 250 bg random \, update;
+#X text 327 250 random color;
+#X obj 20 279 ui.canvas;
+#X connect 0 0 16 0;
+#X connect 2 0 16 0;
+#X connect 4 0 16 0;
+#X connect 6 0 16 0;
+#X connect 8 0 16 0;
+#X connect 10 0 16 0;
+#X connect 12 0 16 0;
+#X connect 14 0 16 0;
diff --git a/ceammc/ext/doc/ui.canvas.image.pd b/ceammc/ext/doc/ui.canvas.image.pd
new file mode 100644
index 0000000000..ce6e93fcb3
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.image.pd
@@ -0,0 +1,14 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 clear \, image 20 20 img/puredata-ceammc.png 0.5 \, update;
+#X msg 20 77 clear \, image -30 -20 img/sample.svg 0.6 \, update;
+#X msg 20 106 clear \, image -30 -20 img/bach.jpg \, update;
+#X msg 20 135 clear \, icon 100 150 120 settings \, stroke navy \, update;
+#X msg 39 164 icon ?;
+#X obj 20 192 ui.canvas @size 300 200;
+#X obj 20 408 ui.link @title See_Material_Icons @url
+https://fonts.google.com/icons;
+#X connect 4 0 5 0;
+#X connect 0 0 5 0;
+#X connect 1 0 5 0;
+#X connect 2 0 5 0;
+#X connect 3 0 5 0;
diff --git a/ceammc/ext/doc/ui.canvas.line.pd b/ceammc/ext/doc/ui.canvas.line.pd
new file mode 100644
index 0000000000..0cc6d562fd
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.line.pd
@@ -0,0 +1,14 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 clear \, line_cap butt \, width 10 \, line 10% 10% 90% 90% \, stroke blue \, update;
+#X msg 20 92 clear \, line_cap square \, width 10 \, line 10% 10% 90% 90% \, stroke blue \, update;
+#X msg 20 135 clear \, line_cap round \, width 10 \, line 10% 10% 90% 90% \, stroke red \, update;
+#X msg 58 178 dash;
+#X msg 154 178 dash 5 5 12;
+#X msg 20 207 clear \, width 10 \, line_cap round \, move_to 10% 50% \, line_to 90% 50% \, line_to 50% 10% \, line_to 50% 90% \, stroke cyan \, update;
+#X obj 20 264 ui.canvas @size 300 200;
+#X connect 0 0 6 0;
+#X connect 1 0 6 0;
+#X connect 2 0 6 0;
+#X connect 5 0 6 0;
+#X connect 3 0 6 0;
+#X connect 4 0 6 0;
diff --git a/ceammc/ext/doc/ui.canvas.matrix.pd b/ceammc/ext/doc/ui.canvas.matrix.pd
new file mode 100644
index 0000000000..e13cd641c1
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.matrix.pd
@@ -0,0 +1,15 @@
+#N canvas 0 0 1000 587 12;
+#X obj 20 48 loadbang;
+#X msg 20 77 clear \, image 20 20 img/2d_matrix.svg 0.32 \, update;
+#X obj 20 106 ui.canvas @size 380 500;
+#X msg 413 106 clear \, matrix 2 0 0 2 0 0 \, rect 50 50 100 100 \, stroke red \, update;
+#X msg 423 149 clear \, matrix 2 0 0 2 50 70 \, rect 50 50 100 100 \, stroke red \, update;
+#X msg 432 192 clear \, matrix 2.5 0 0 1.5 0 0 \, rect 50 50 100 100 \, stroke red \, update;
+#X msg 442 235 clear \, matrix 2 0.5 0 2 0 0 \, rect 50 50 100 100 \, stroke red \, update;
+#X obj 413 293 ui.canvas @size 300 200;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 3 0 7 0;
+#X connect 4 0 7 0;
+#X connect 5 0 7 0;
+#X connect 6 0 7 0;
diff --git a/ceammc/ext/doc/ui.canvas.music.pd b/ceammc/ext/doc/ui.canvas.music.pd
new file mode 100644
index 0000000000..b65b9e56e6
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.music.pd
@@ -0,0 +1,11 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 clear \, musicxml -100 -20 music/simple.mxml 120 \, update;
+#X obj 39 77 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 39 106 openpanel;
+#X msg 39 135 clear \, musicxml 0 0 \$1 50 \, update;
+#X obj 20 164 ui.canvas @size 500 400;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 0 0 4 0;
diff --git a/ceammc/ext/doc/ui.canvas.text.pd b/ceammc/ext/doc/ui.canvas.text.pd
new file mode 100644
index 0000000000..f9403894c5
--- /dev/null
+++ b/ceammc/ext/doc/ui.canvas.text.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 956 587 12;
+#X msg 20 48 clear \, matrix \, translate 50% 50%;
+#X msg 29 77 rotate 30 \, font Verdana \, font_size 20 \, text 20 0 CEAM \, fill random \, update;
+#X msg 39 120 matrix \, font Verdana bold \, font_size 40 \, width 2 \, text 50 75 HELLO \, fill gray preserve \, stroke cyan \, update;
+#X msg 48 164 clear \, font Verdana italic \, font_size 50 \, text 50 75 HELLO \, fill black \, update;
+#X msg 58 207 clear \, font Verdana italic bold 60 \, text 25% 75 HELLO \, fill black \, update;
+#X obj 20 250 ui.canvas @size 300 200;
+#X connect 0 0 5 0;
+#X connect 1 0 5 0;
+#X connect 2 0 5 0;
+#X connect 3 0 5 0;
+#X connect 4 0 5 0;
diff --git a/ceammc/ext/src/conv/mod_conv.cpp b/ceammc/ext/src/conv/mod_conv.cpp
index ee6383796b..242dd07a26 100644
--- a/ceammc/ext/src/conv/mod_conv.cpp
+++ b/ceammc/ext/src/conv/mod_conv.cpp
@@ -50,6 +50,7 @@ void setup_conv_bits2pos();
void setup_conv_char2morse();
void setup_conv_guido2note();
void setup_conv_note2guido();
+void setup_conv_char2morse();
void ceammc_conv_setup()
{
@@ -103,4 +104,5 @@ void ceammc_conv_setup()
setup_conv_char2morse();
setup_conv_guido2note();
setup_conv_note2guido();
+ setup_conv_char2morse();
}
diff --git a/ceammc/ext/src/fx/fx_looper.cpp b/ceammc/ext/src/fx/fx_looper.cpp
index f980edf668..c67440970c 100644
--- a/ceammc/ext/src/fx/fx_looper.cpp
+++ b/ceammc/ext/src/fx/fx_looper.cpp
@@ -210,6 +210,9 @@ void FxLooper::initDone()
OBJ_DBG << fmt::format("using default loop length: {}", len_sec);
}
+ debug_ = new BoolProperty("@debug", true);
+ addProperty(debug_);
+
resizeBuffer();
calcXFades();
OBJ_DBG << fmt::format("max loop length {} samples ({} sec)", max_samples_, capacity_sec_->value());
diff --git a/ceammc/ext/src/lib/CMakeLists.txt b/ceammc/ext/src/lib/CMakeLists.txt
index 85e3e568d9..1d3a41fca3 100644
--- a/ceammc/ext/src/lib/CMakeLists.txt
+++ b/ceammc/ext/src/lib/CMakeLists.txt
@@ -259,6 +259,15 @@ if(LIBLO_FOUND)
endif()
target_sources(ceammc_core PRIVATE ceammc_osc.cpp)
+# liblo
+find_package(liblo)
+if(LIBLO_FOUND)
+ target_compile_definitions(ceammc_core PRIVATE WITH_LIBLO)
+ target_include_directories(ceammc_core PRIVATE ${LIBLO_INCLUDE_DIRS})
+ target_link_libraries(ceammc_core PUBLIC ${LIBLO_LIBRARIES})
+endif()
+target_sources(ceammc_core PRIVATE ceammc_osc.cpp)
+
if(BISON_FOUND AND FLEX_FOUND)
add_custom_target(ceammc_arrayloader_gen
COMMAND $ array_loader.l
diff --git a/ceammc/ext/src/lib/ceammc_atomlist.cpp b/ceammc/ext/src/lib/ceammc_atomlist.cpp
index b67159a5f3..1f0955cca5 100644
--- a/ceammc/ext/src/lib/ceammc_atomlist.cpp
+++ b/ceammc/ext/src/lib/ceammc_atomlist.cpp
@@ -420,6 +420,41 @@ AtomListView AtomList::asLogicList() const noexcept
return {};
}
+bool AtomList::isMsgAny() const noexcept
+{
+ if (atoms_.size() > 0 && atoms_[0].isSymbol()) {
+ auto& f = atoms_[0];
+ return f != &s_bang && f != &s_float && f != &s_symbol && f != &s_pointer && f != &s_list;
+ } else
+ return false;
+}
+
+t_float AtomList::asMsgFloat(t_float def) const noexcept
+{
+ if (isMsgFloat())
+ return atoms_[1].asT();
+ else
+ return def;
+}
+
+t_symbol* AtomList::asMsgSymbol(t_symbol* def) const noexcept
+{
+ if (isMsgSymbol())
+ return atoms_[1].asT();
+ else
+ return def;
+}
+
+AtomListView AtomList::asLogicList() const noexcept
+{
+ if (isMsgList())
+ return view(1);
+ else if (atoms_.size() > 1 && atoms_[0].isFloat())
+ return view();
+ else
+ return {};
+}
+
void AtomList::fill(const Atom& a)
{
std::fill(atoms_.begin(), atoms_.end(), a);
diff --git a/ceammc/ext/src/misc/fluid.cpp b/ceammc/ext/src/misc/fluid.cpp
index 043102c4ab..6a025d9335 100644
--- a/ceammc/ext/src/misc/fluid.cpp
+++ b/ceammc/ext/src/misc/fluid.cpp
@@ -744,6 +744,15 @@ void Fluid::m_tune_semi(t_symbol* s, const AtomListView& lv)
callFluidChannelFn(s, ch.chan, fn, ch.value, TUNE_CENTS_VALUE_NAME, lv);
}
+struct StreamGuard {
+ ArgChecker& check;
+ StreamGuard(ArgChecker& chk)
+ : check(chk)
+ {
+ }
+ ~StreamGuard() { check.setOut(std::cerr); }
+};
+
void Fluid::m_tune_octave(t_symbol* s, const AtomListView& lv)
{
static const args::ArgChecker chk("BANK:i PROG:i f f f f f f f f f f f f");
diff --git a/ceammc/ext/src/proto/proto_midi.cpp b/ceammc/ext/src/proto/proto_midi.cpp
index b99861404f..4dd4e94f9d 100644
--- a/ceammc/ext/src/proto/proto_midi.cpp
+++ b/ceammc/ext/src/proto/proto_midi.cpp
@@ -300,6 +300,25 @@ void ProtoMidi::m_raw(t_symbol* s, const AtomListView& lv)
}
}
+void ProtoMidi::m_raw(t_symbol* s, const AtomListView& lv)
+{
+ std::uint8_t b = 0;
+ for (auto& a : lv) {
+ if (a.isSymbol()) {
+ if (!parser::parse_midi_byte_hex(a, b)) {
+ METHOD_ERR(s) << "byte or hex is expected, got: " << a;
+ continue;
+ }
+ } else if (a.isFloat())
+ b = a.asT();
+
+ if (b < 0 || b > 0xFF)
+ METHOD_ERR(s) << "invalid byte value: " << b;
+ else
+ floatTo(0, b);
+ }
+}
+
void ProtoMidi::m_songPosition(t_symbol* s, const AtomListView& lv)
{
if (lv.size() < 1) {
@@ -552,6 +571,37 @@ void ProtoMidi::m_allSoundOff(t_symbol* s, const AtomListView& lv)
}
}
+void ProtoMidi::m_allNotesOff(t_symbol* s, const AtomListView& lv)
+{
+ static const args::ArgChecker chk("CHAN:i[0,15]?");
+ if (!chk.check(lv, this))
+ return chk.usage(this, s);
+
+ auto chan = lv.intAt(0, -1);
+
+ if (chan < 0) {
+ for (int i = 0; i < 16; i++)
+ sendBytes3(i, midi::MIDI_CONTROLCHANGE, CC_ALL_NOTES_OFF, 0x7F);
+ } else {
+ sendBytes3(chan, midi::MIDI_CONTROLCHANGE, CC_ALL_NOTES_OFF, 0x7F);
+ }
+}
+
+void ProtoMidi::m_allSoundOff(t_symbol* s, const AtomListView& lv)
+{
+ static const args::ArgChecker chk("CHAN:i[0,15]?");
+ if (!chk.check(lv, this))
+ return chk.usage(this, s);
+
+ auto chan = lv.intAt(0, -1);
+ if (chan < 0) {
+ for (int i = 0; i < 16; i++)
+ sendBytes3(i, midi::MIDI_CONTROLCHANGE, CC_ALL_SOUND_OFF, 0x7F);
+ } else {
+ sendBytes3(chan, midi::MIDI_CONTROLCHANGE, CC_ALL_SOUND_OFF, 0x7F);
+ }
+}
+
void ProtoMidi::m_cc(t_symbol* s, const AtomListView& lv)
{
if (!checkMethodByte3(s, lv)) {
diff --git a/ceammc/ext/src/proto/proto_midi_parser.h b/ceammc/ext/src/proto/proto_midi_parser.h
index 50eacefcd6..34e0f72610 100644
--- a/ceammc/ext/src/proto/proto_midi_parser.h
+++ b/ceammc/ext/src/proto/proto_midi_parser.h
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
diff --git a/ceammc/ext/src/ui/ui_incdec.cpp b/ceammc/ext/src/ui/ui_incdec.cpp
index 4a8eaa3e7b..0943b4a3d3 100644
--- a/ceammc/ext/src/ui/ui_incdec.cpp
+++ b/ceammc/ext/src/ui/ui_incdec.cpp
@@ -27,6 +27,16 @@ enum {
MODE_DEC = -1
};
+constexpr int MAX_VALUE_DEFAULT = 8192;
+constexpr int MIN_VALUE_DEFAULT = -MAX_VALUE_DEFAULT;
+constexpr int FLASH_MS = 100;
+
+enum {
+ MODE_NONE = 0,
+ MODE_INC = 1,
+ MODE_DEC = -1
+};
+
UIIncDec::UIIncDec()
: UIBindObject<2> { { [this](int v) { m_inc(); }, [this](int v) { m_dec(); } } }
, prop_color_arrow(rgba_greydark)
diff --git a/ceammc/ext/src/ui/ui_label.cpp b/ceammc/ext/src/ui/ui_label.cpp
index d63698a38a..49867b7b6e 100644
--- a/ceammc/ext/src/ui/ui_label.cpp
+++ b/ceammc/ext/src/ui/ui_label.cpp
@@ -13,6 +13,7 @@
*****************************************************************************/
#include "ui_label.h"
#include "ceammc_abstractdata.h"
+#include "ceammc_canvas.h"
#include "ceammc_containers.h"
#include "ceammc_crc32.h"
#include "ceammc_format.h"
diff --git a/ceammc/ext/src/ui/ui_touchosc.cpp b/ceammc/ext/src/ui/ui_touchosc.cpp
index 8c93404ed9..7d403ec066 100644
--- a/ceammc/ext/src/ui/ui_touchosc.cpp
+++ b/ceammc/ext/src/ui/ui_touchosc.cpp
@@ -16,6 +16,8 @@
#include "ceammc_factory.h"
#include "ceammc_format.h"
#include "ceammc_platform.h"
+#include "ceammc_poll_dispatcher.h"
+#include "ceammc_thread.h"
//#include "ceammc_thread.h"
#include "fmt/core.h"
diff --git a/ceammc/extra/verovio/verovio b/ceammc/extra/verovio/verovio
index da4bac485c..ec1ae463ae 160000
--- a/ceammc/extra/verovio/verovio
+++ b/ceammc/extra/verovio/verovio
@@ -1 +1 @@
-Subproject commit da4bac485ca65636d2d3fac037bf5e26c021721c
+Subproject commit ec1ae463ae1a3343924526db146d3f766e923e91
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index e776018e36..4ee13f02a1 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -130,7 +130,6 @@ parts:
- libmagic-dev
- libmodplug-dev
- librubberband-dev
- - libsamplerate0-dev
- libsndfile1-dev
- libssl-dev
- libudev-dev
@@ -164,7 +163,6 @@ parts:
- libmagic1
- libmodplug1
- librubberband2
- - libsamplerate0
- libsndfile1
- libssl1.1
- libtcl8.6