From 0d4751cfaf0703c91921e4ecd8bdcf83f8f281c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigrid=20Hafl=C3=ADnud=C3=B3ttir?= Date: Tue, 5 May 2020 14:45:00 +0200 Subject: [PATCH 1/3] guide for the cell under the cursor in the HUD --- base.h | 1 + ops.h | 39 +++++++++ sim.c | 253 ++++++++++++++++++++++++++--------------------------- sim.h | 8 +- tui_main.c | 32 +++++-- 5 files changed, 195 insertions(+), 138 deletions(-) create mode 100644 ops.h diff --git a/base.h b/base.h index e067300..21fc9e9 100644 --- a/base.h +++ b/base.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/ops.h b/ops.h new file mode 100644 index 0000000..1d43bcc --- /dev/null +++ b/ops.h @@ -0,0 +1,39 @@ +#pragma once + +#define UNIQUE_OPERATORS(_) \ + _('!', midicc, "CC", "Sends MIDI control change") \ + _('#', comment, "Comment", "Halts line") \ + _('%', midi, "Mono", "Sends MIDI monophonic note") \ + _('*', bang, "Bang", "Bangs neighboring operands") \ + _(':', midi, "Midi", "Sends MIDI note") \ + _(';', udp, "UDP", "Sends UDP message") \ + _('=', osc, "OSC", "Sends OSC message") \ + _('?', midipb, "PB", "Sends MIDI pitch bend") + +#define ALPHA_OPERATORS(_) \ + _('A', add, "Add", "Outputs sum of inputs") \ + _('B', subtract, "Subtract", "Outputs difference of inputs") \ + _('C', clock, "Clock", "Outputs modulo of frame") \ + _('D', delay, "Delay", "Bangs on modulo of frame") \ + _('E', movement, "East", "Moves eastward, or bangs") \ + _('F', if, "If", "Bangs if inputs are equal") \ + _('G', generator, "Generator", "Writes operands with offset") \ + _('H', halt, "Halt", "Halts southward operand") \ + _('I', increment, "Increment", "Increments southward operand") \ + _('J', jump, "Jumper", "Outputs northward operand") \ + _('K', konkat, "Konkat", "Reads multiple variables") \ + _('L', lesser, "Lesser", "Outputs smallest input") \ + _('M', multiply, "Multiply", "Outputs product of inputs") \ + _('N', movement, "North", "Moves Northward, or bangs") \ + _('O', offset, "Read", "Reads operand with offset") \ + _('P', push, "Push", "Writes eastward operand") \ + _('Q', query, "Query", "Reads operands with offset") \ + _('R', random, "Random", "Outputs random value") \ + _('S', movement, "South", "Moves southward, or bangs") \ + _('T', track, "Track", "Reads eastward operand") \ + _('U', uclid, "Uclid", "Bangs on Euclidean rhythm") \ + _('V', variable, "Variable", "Reads and writes variable") \ + _('W', movement, "West", "Moves westward, or bangs") \ + _('X', teleport, "Write", "Writes operand with offset") \ + _('Y', yump, "Jymper", "Outputs westward operand") \ + _('Z', lerp, "Lerp", "Transitions operand to target") diff --git a/sim.c b/sim.c index 5ad58e5..e40ce24 100644 --- a/sim.c +++ b/sim.c @@ -1,5 +1,6 @@ #include "sim.h" #include "gbuffer.h" +#include "ops.h" //////// Utilities @@ -99,7 +100,7 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer, Glyph *const restrict gbuffer, Mark *const restrict mbuffer, \ Usz const height, Usz const width, Usz const y, Usz const x, \ Usz Tick_number, Oper_extra_params *const extra_params, \ - Mark const cell_flags, Glyph const This_oper_char) { \ + Mark const cell_flags, Glyph const This_oper_char, Guide *guide) { \ (void)gbuffer; \ (void)mbuffer; \ (void)height; \ @@ -109,7 +110,8 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer, (void)Tick_number; \ (void)extra_params; \ (void)cell_flags; \ - (void)This_oper_char; + (void)This_oper_char; \ + (void)guide; #define END_OPERATOR } @@ -142,48 +144,17 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer, if (!oper_has_neighboring_bang(gbuffer, height, width, y, x)) \ return -#define PORT(_delta_y, _delta_x, _flags) \ +#define PORT(_delta_y, _delta_x, _flags, _name) \ + { \ + Isz x0 = (Isz)x + _delta_x; \ + Isz y0 = (Isz)y + _delta_y; \ + if ((Usz)x0 == guide->x && (Usz)y0 == guide->y) { \ + snprintf(guide->name, sizeof(guide->name), "%c-%s", This_oper_char, \ + _name); \ + } \ + } \ mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ _delta_x, (_flags) ^ Mark_flag_lock) -//////// Operators - -#define UNIQUE_OPERATORS(_) \ - _('!', midicc) \ - _('#', comment) \ - _('%', midi) \ - _('*', bang) \ - _(':', midi) \ - _(';', udp) \ - _('=', osc) \ - _('?', midipb) - -#define ALPHA_OPERATORS(_) \ - _('A', add) \ - _('B', subtract) \ - _('C', clock) \ - _('D', delay) \ - _('E', movement) \ - _('F', if) \ - _('G', generator) \ - _('H', halt) \ - _('I', increment) \ - _('J', jump) \ - _('K', konkat) \ - _('L', lesser) \ - _('M', multiply) \ - _('N', movement) \ - _('O', offset) \ - _('P', push) \ - _('Q', query) \ - _('R', random) \ - _('S', movement) \ - _('T', track) \ - _('U', uclid) \ - _('V', variable) \ - _('W', movement) \ - _('X', teleport) \ - _('Y', yump) \ - _('Z', lerp) BEGIN_OPERATOR(movement) if (glyph_is_lowercase(This_oper_char) && @@ -230,9 +201,9 @@ BEGIN_OPERATOR(movement) END_OPERATOR BEGIN_OPERATOR(midicc) - for (Usz i = 1; i < 4; ++i) { - PORT(0, (Isz)i, IN); - } + PORT(0, 1, IN, "channel"); + PORT(0, 2, IN, "knob"); + PORT(0, 3, IN, "value"); STOP_IF_NOT_BANGED; Glyph channel_g = PEEK(0, 1); Glyph control_g = PEEK(0, 2); @@ -270,9 +241,11 @@ BEGIN_OPERATOR(bang) END_OPERATOR BEGIN_OPERATOR(midi) - for (Usz i = 1; i < 6; ++i) { - PORT(0, (Isz)i, IN); - } + PORT(0, 1, IN, "channel"); + PORT(0, 2, IN, "octave"); + PORT(0, 3, IN, "note"); + PORT(0, 4, IN, "velocity"); + PORT(0, 5, IN, "length"); STOP_IF_NOT_BANGED; Glyph channel_g = PEEK(0, 1); Glyph octave_g = PEEK(0, 2); @@ -345,13 +318,13 @@ BEGIN_OPERATOR(udp) END_OPERATOR BEGIN_OPERATOR(osc) - PORT(0, 1, IN | PARAM); - PORT(0, 2, IN | PARAM); + PORT(0, 1, IN | PARAM, "path"); + PORT(0, 2, IN | PARAM, "len"); Usz len = index_of(PEEK(0, 2)); if (len > Oevent_osc_int_count) len = Oevent_osc_int_count; for (Usz i = 0; i < len; ++i) { - PORT(0, (Isz)i + 3, IN); + PORT(0, (Isz)i + 3, IN, "in"); } STOP_IF_NOT_BANGED; Glyph g = PEEK(0, 1); @@ -372,9 +345,9 @@ BEGIN_OPERATOR(osc) END_OPERATOR BEGIN_OPERATOR(midipb) - for (Usz i = 1; i < 4; ++i) { - PORT(0, (Isz)i, IN); - } + PORT(0, 1, IN, "channel"); + PORT(0, 2, IN, "lsb"); + PORT(0, 3, IN, "msb"); STOP_IF_NOT_BANGED; Glyph channel_g = PEEK(0, 1); Glyph msb_g = PEEK(0, 2); @@ -394,9 +367,9 @@ END_OPERATOR BEGIN_OPERATOR(add) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "a"); + PORT(0, 1, IN, "b"); + PORT(1, 0, OUT, "output"); Glyph a = PEEK(0, -1); Glyph b = PEEK(0, 1); Glyph g = glyph_table[(index_of(a) + index_of(b)) % Glyphs_index_count]; @@ -405,9 +378,9 @@ END_OPERATOR BEGIN_OPERATOR(subtract) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "a"); + PORT(0, 1, IN, "b"); + PORT(1, 0, OUT, "output"); Glyph a = PEEK(0, -1); Glyph b = PEEK(0, 1); Isz val = (Isz)index_of(b) - (Isz)index_of(a); @@ -418,9 +391,9 @@ END_OPERATOR BEGIN_OPERATOR(clock) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "rate"); + PORT(0, 1, IN, "mod"); + PORT(1, 0, OUT, "output"); Usz rate = index_of(PEEK(0, -1)); Usz mod_num = index_of(PEEK(0, 1)); if (rate == 0) @@ -433,9 +406,9 @@ END_OPERATOR BEGIN_OPERATOR(delay) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "rate"); + PORT(0, 1, IN, "mod"); + PORT(1, 0, OUT, "output"); Usz rate = index_of(PEEK(0, -1)); Usz mod_num = index_of(PEEK(0, 1)); if (rate == 0) @@ -448,9 +421,9 @@ END_OPERATOR BEGIN_OPERATOR(if) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "a"); + PORT(0, 1, IN, "b"); + PORT(1, 0, OUT, "output"); Glyph g0 = PEEK(0, -1); Glyph g1 = PEEK(0, 1); POKE(1, 0, g0 == g1 ? '*' : '.'); @@ -461,12 +434,15 @@ BEGIN_OPERATOR(generator) Isz out_x = (Isz)index_of(PEEK(0, -3)); Isz out_y = (Isz)index_of(PEEK(0, -2)) + 1; Isz len = (Isz)index_of(PEEK(0, -1)); - PORT(0, -3, IN | PARAM); // x - PORT(0, -2, IN | PARAM); // y - PORT(0, -1, IN | PARAM); // len + PORT(0, -3, IN | PARAM, "x"); + PORT(0, -2, IN | PARAM, "y"); + PORT(0, -1, IN | PARAM, "len"); for (Isz i = 0; i < len; ++i) { - PORT(0, i + 1, IN); - PORT(out_y, out_x + i, OUT | NONLOCKING); + char t[6]; + sprintf(t, "in%ld", i); + PORT(0, i + 1, IN, t); + sprintf(t, "out%ld", i); + PORT(out_y, out_x + i, OUT | NONLOCKING, t); Glyph g = PEEK(0, i + 1); POKE_STUNNED(out_y, out_x + i, g); } @@ -474,14 +450,14 @@ END_OPERATOR BEGIN_OPERATOR(halt) LOWERCASE_REQUIRES_BANG; - PORT(1, 0, OUT); + PORT(1, 0, OUT, "output"); END_OPERATOR BEGIN_OPERATOR(increment) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, IN | OUT); + PORT(0, -1, IN | PARAM, "step"); + PORT(0, 1, IN, "mod"); + PORT(1, 0, IN | OUT, "output"); Glyph ga = PEEK(0, -1); Glyph gb = PEEK(0, 1); Usz rate = 1; @@ -498,8 +474,8 @@ END_OPERATOR BEGIN_OPERATOR(jump) LOWERCASE_REQUIRES_BANG; - PORT(-1, 0, IN); - PORT(1, 0, OUT); + PORT(-1, 0, IN, "val"); + PORT(1, 0, OUT, "output"); POKE(1, 0, PEEK(-1, 0)); END_OPERATOR @@ -510,15 +486,18 @@ BEGIN_OPERATOR(konkat) Isz len = (Isz)index_of(PEEK(0, -1)); if (len == 0) len = 1; - PORT(0, -1, IN | PARAM); + PORT(0, -1, IN | PARAM, "len"); for (Isz i = 0; i < len; ++i) { - PORT(0, i + 1, IN); + char t[6]; + sprintf(t, "in%ld", i); + PORT(0, i + 1, IN, t); Glyph var = PEEK(0, i + 1); if (var != '.') { Usz var_idx = index_of(var); if (var_idx != 0) { Glyph result = extra_params->vars_slots[var_idx]; - PORT(1, i + 1, OUT); + sprintf(t, "out%ld", i); + PORT(1, i + 1, OUT, t); POKE(1, i + 1, result); } } @@ -527,9 +506,9 @@ END_OPERATOR BEGIN_OPERATOR(lesser) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "a"); + PORT(0, 1, IN, "b"); + PORT(1, 0, OUT, "output"); Glyph ga = PEEK(0, -1); Glyph gb = PEEK(0, 1); if (ga == '.' || gb == '.') { @@ -544,9 +523,9 @@ END_OPERATOR BEGIN_OPERATOR(multiply) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "a"); + PORT(0, 1, IN, "b"); + PORT(1, 0, OUT, "output"); Glyph a = PEEK(0, -1); Glyph b = PEEK(0, 1); Glyph g = glyph_table[(index_of(a) * index_of(b)) % Glyphs_index_count]; @@ -557,10 +536,10 @@ BEGIN_OPERATOR(offset) LOWERCASE_REQUIRES_BANG; Isz in_x = (Isz)index_of(PEEK(0, -2)) + 1; Isz in_y = (Isz)index_of(PEEK(0, -1)); - PORT(0, -1, IN | PARAM); - PORT(0, -2, IN | PARAM); - PORT(in_y, in_x, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "y"); + PORT(0, -2, IN | PARAM, "x"); + PORT(in_y, in_x, IN, "read"); + PORT(1, 0, OUT, "output"); POKE(1, 0, PEEK(in_y, in_x)); END_OPERATOR @@ -568,16 +547,16 @@ BEGIN_OPERATOR(push) LOWERCASE_REQUIRES_BANG; Usz key = index_of(PEEK(0, -2)); Usz len = index_of(PEEK(0, -1)); - PORT(0, -1, IN | PARAM); - PORT(0, -2, IN | PARAM); - PORT(0, 1, IN); + PORT(0, -1, IN | PARAM, "len"); + PORT(0, -2, IN | PARAM, "key"); + PORT(0, 1, IN, "val"); if (len == 0) return; Isz out_x = (Isz)(key % len); for (Usz i = 0; i < len; ++i) { LOCK(1, (Isz)i); } - PORT(1, out_x, OUT); + PORT(1, out_x, OUT, "output"); POKE(1, out_x, PEEK(0, 1)); END_OPERATOR @@ -587,13 +566,16 @@ BEGIN_OPERATOR(query) Isz in_y = (Isz)index_of(PEEK(0, -2)); Isz len = (Isz)index_of(PEEK(0, -1)); Isz out_x = 1 - len; - PORT(0, -3, IN | PARAM); // x - PORT(0, -2, IN | PARAM); // y - PORT(0, -1, IN | PARAM); // len + PORT(0, -3, IN | PARAM, "x"); + PORT(0, -2, IN | PARAM, "y"); + PORT(0, -1, IN | PARAM, "len"); // todo direct buffer manip for (Isz i = 0; i < len; ++i) { - PORT(in_y, in_x + i, IN); - PORT(1, out_x + i, OUT); + char t[6]; + sprintf(t, "in%ld", i); + PORT(in_y, in_x + i, IN, t); + sprintf(t, "out%ld", i); + PORT(1, out_x + i, OUT, t); Glyph g = PEEK(in_y, in_x + i); POKE(1, out_x + i, g); } @@ -601,9 +583,9 @@ END_OPERATOR BEGIN_OPERATOR(random) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "min"); + PORT(0, 1, IN, "max"); + PORT(1, 0, OUT, "val"); Usz a = index_of(PEEK(0, -1)); Usz b = index_of(PEEK(0, 1)); if (b == 0) @@ -637,16 +619,16 @@ BEGIN_OPERATOR(track) LOWERCASE_REQUIRES_BANG; Usz key = index_of(PEEK(0, -2)); Usz len = index_of(PEEK(0, -1)); - PORT(0, -2, IN | PARAM); - PORT(0, -1, IN | PARAM); + PORT(0, -2, IN | PARAM, "key"); + PORT(0, -1, IN | PARAM, "len"); if (len == 0) return; Isz read_val_x = (Isz)(key % len) + 1; for (Usz i = 0; i < len; ++i) { LOCK(0, (Isz)(i + 1)); } - PORT(0, (Isz)read_val_x, IN); - PORT(1, 0, OUT); + PORT(0, (Isz)read_val_x, IN, "val"); + PORT(1, 0, OUT, "output"); POKE(1, 0, PEEK(0, read_val_x)); END_OPERATOR @@ -654,9 +636,9 @@ END_OPERATOR // simplest-euclidean-rhythm-algorithm-explained/ BEGIN_OPERATOR(uclid) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, OUT); + PORT(0, -1, IN | PARAM, "write"); + PORT(0, 1, IN, "read"); + PORT(1, 0, OUT, "output"); Glyph left = PEEK(0, -1); Usz steps = 1; if (left != '.' && left != '*') @@ -671,8 +653,8 @@ END_OPERATOR BEGIN_OPERATOR(variable) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); + PORT(0, -1, IN | PARAM, "write"); + PORT(0, 1, IN, "read"); Glyph left = PEEK(0, -1); Glyph right = PEEK(0, 1); if (left != '.') { @@ -681,7 +663,7 @@ BEGIN_OPERATOR(variable) extra_params->vars_slots[var_idx] = right; } else if (right != '.') { // Read - PORT(1, 0, OUT); + PORT(1, 0, OUT, "output"); Usz var_idx = index_of(right); Glyph result = extra_params->vars_slots[var_idx]; POKE(1, 0, result); @@ -692,25 +674,25 @@ BEGIN_OPERATOR(teleport) LOWERCASE_REQUIRES_BANG; Isz out_x = (Isz)index_of(PEEK(0, -2)); Isz out_y = (Isz)index_of(PEEK(0, -1)) + 1; - PORT(0, -2, IN | PARAM); // x - PORT(0, -1, IN | PARAM); // y - PORT(0, 1, IN); - PORT(out_y, out_x, OUT | NONLOCKING); + PORT(0, -2, IN | PARAM, "x"); + PORT(0, -1, IN | PARAM, "y"); + PORT(0, 1, IN, "val"); + PORT(out_y, out_x, OUT | NONLOCKING, "output"); POKE_STUNNED(out_y, out_x, PEEK(0, 1)); END_OPERATOR BEGIN_OPERATOR(yump) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN); - PORT(0, 1, OUT); + PORT(0, -1, IN, "val"); + PORT(0, 1, OUT, "output"); POKE(0, 1, PEEK(0, -1)); END_OPERATOR BEGIN_OPERATOR(lerp) LOWERCASE_REQUIRES_BANG; - PORT(0, -1, IN | PARAM); - PORT(0, 1, IN); - PORT(1, 0, IN | OUT); + PORT(0, -1, IN | PARAM, "rate"); + PORT(0, 1, IN, "target"); + PORT(1, 0, IN | OUT, "output"); Glyph g = PEEK(0, -1); Isz rate = g == '.' || g == '*' ? 1 : (Isz)index_of(g); Isz goal = (Isz)index_of(PEEK(0, 1)); @@ -721,8 +703,9 @@ END_OPERATOR //////// Run simulation -void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width, - Usz tick_number, Oevent_list *oevent_list, Usz random_seed) { +void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, + Usz width, Usz tick_number, Oevent_list *oevent_list, + Usz random_seed, Guide *guide) { Glyph vars_slots[Glyphs_index_count]; memset(vars_slots, '.', sizeof(vars_slots)); Oper_extra_params extras; @@ -730,6 +713,10 @@ void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width, extras.oevent_list = oevent_list; extras.random_seed = random_seed; + const char *name = "empty"; + strncpy(guide->name, name, sizeof(guide->name)-1); + guide->name[sizeof(guide->name)-1] = 0; + for (Usz iy = 0; iy < height; ++iy) { Glyph const *glyph_row = gbuf + iy * width; Mark const *mark_row = mbuf + iy * width; @@ -741,23 +728,29 @@ void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width, if (cell_flags & (Mark_flag_lock | Mark_flag_sleep)) continue; switch (glyph_char) { -#define UNIQUE_CASE(_oper_char, _oper_name) \ +#define UNIQUE_CASE(_oper_char, _oper_name, _hr_name, _hr_desc) \ case _oper_char: \ + name = _hr_name; \ oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \ - &extras, cell_flags, glyph_char); \ + &extras, cell_flags, glyph_char, guide); \ break; -#define ALPHA_CASE(_upper_oper_char, _oper_name) \ +#define ALPHA_CASE(_upper_oper_char, _oper_name, _hr_name, _hr_desc) \ case _upper_oper_char: \ case (char)(_upper_oper_char | 1 << 5): \ + name = _hr_name; \ oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \ - &extras, cell_flags, glyph_char); \ + &extras, cell_flags, glyph_char, guide); \ break; UNIQUE_OPERATORS(UNIQUE_CASE) ALPHA_OPERATORS(ALPHA_CASE) #undef UNIQUE_CASE #undef ALPHA_CASE } + if (ix == guide->x && iy == guide->y) { + strncpy(guide->name, name, sizeof(guide->name)-1); + guide->name[sizeof(guide->name)-1] = 0; + } } } } diff --git a/sim.h b/sim.h index 1c10283..5edb838 100644 --- a/sim.h +++ b/sim.h @@ -2,6 +2,12 @@ #include "base.h" #include "vmio.h" +typedef struct { + char name[8]; + Usz x; + Usz y; +}Guide; + void orca_run(Glyph *restrict gbuffer, Mark *restrict mbuffer, Usz height, Usz width, Usz tick_number, Oevent_list *oevent_list, - Usz random_seed); + Usz random_seed, Guide *guide); diff --git a/tui_main.c b/tui_main.c index 45b72f4..cdbaaf8 100644 --- a/tui_main.c +++ b/tui_main.c @@ -461,11 +461,18 @@ staticni void draw_hud(WINDOW *win, int win_y, int win_x, int height, int width, char const *filename, Usz field_h, Usz field_w, Usz ruler_spacing_y, Usz ruler_spacing_x, Usz tick_num, Usz bpm, Ged_cursor const *ged_cursor, - Ged_input_mode input_mode, Usz activity_counter) { + Ged_input_mode input_mode, Usz activity_counter, + Guide const *guide) { (void)height; (void)width; enum { Tabstop = 8 }; wmove(win, win_y, win_x); + if (ged_cursor->w > 1 || ged_cursor->h > 1) { + wprintw(win, "multi"); + } else { + wprintw(win, "%.*s", Tabstop-1, guide->name); + } + advance_faketab(win, win_x, Tabstop); wprintw(win, "%zux%zu", field_w, field_h); advance_faketab(win, win_x, Tabstop); wprintw(win, "%zu/%zu", ruler_spacing_x, ruler_spacing_y); @@ -476,6 +483,8 @@ staticni void draw_hud(WINDOW *win, int win_y, int win_x, int height, int width, advance_faketab(win, win_x, Tabstop); print_activity_indicator(win, activity_counter); wmove(win, win_y + 1, win_x); + // vacant spot here + advance_faketab(win, win_x, Tabstop); wprintw(win, "%zu,%zu", ged_cursor->x, ged_cursor->y); advance_faketab(win, win_x, Tabstop); wprintw(win, "%zu:%zu", ged_cursor->w, ged_cursor->h); @@ -882,6 +891,7 @@ typedef struct { Oevent_list scratch_oevent_list; Susnote_list susnote_list; Ged_cursor ged_cursor; + Guide guide; Usz tick_num; Usz ruler_spacing_y, ruler_spacing_x; Ged_input_mode input_mode; @@ -1262,10 +1272,12 @@ static double ged_secs_to_deadline(Ged const *a) { staticni void clear_and_run_vm(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width, Usz tick_number, - Oevent_list *oevent_list, Usz random_seed) { + Oevent_list *oevent_list, Usz random_seed, + Guide *guide) { mbuffer_clear(mbuf, height, width); oevent_list_clear(oevent_list); - orca_run(gbuf, mbuf, height, width, tick_number, oevent_list, random_seed); + orca_run(gbuf, mbuf, height, width, tick_number, oevent_list, random_seed, + guide); } staticni void ged_do_stuff(Ged *a) { @@ -1323,9 +1335,11 @@ staticni void ged_do_stuff(Ged *a) { } apply_time_to_sustained_notes(oosc_dev, midi_mode, secs_span, &a->susnote_list, &a->time_to_next_note_off); + a->guide.x = a->ged_cursor.x; + a->guide.y = a->ged_cursor.y; clear_and_run_vm(a->field.buffer, a->mbuf_r.buffer, a->field.height, a->field.width, a->tick_num, &a->oevent_list, - a->random_seed); + a->random_seed, &a->guide); ++a->tick_num; a->needs_remarking = true; a->is_draw_dirty = true; @@ -1428,9 +1442,11 @@ staticni void ged_draw(Ged *a, WINDOW *win, char const *filename, a->field.width); field_copy(&a->field, &a->scratch_field); mbuf_reusable_ensure_size(&a->mbuf_r, a->field.height, a->field.width); + a->guide.x = a->ged_cursor.x; + a->guide.y = a->ged_cursor.y; clear_and_run_vm(a->scratch_field.buffer, a->mbuf_r.buffer, a->field.height, a->field.width, a->tick_num, &a->scratch_oevent_list, - a->random_seed); + a->random_seed, &a->guide); a->needs_remarking = false; } int win_w = a->win_w; @@ -1449,7 +1465,7 @@ staticni void ged_draw(Ged *a, WINDOW *win, char const *filename, draw_hud(win, a->grid_h, hud_x, Hud_height, win_w, filename, a->field.height, a->field.width, a->ruler_spacing_y, a->ruler_spacing_x, a->tick_num, a->bpm, &a->ged_cursor, - a->input_mode, a->activity_counter); + a->input_mode, a->activity_counter, &a->guide); } if (a->draw_event_list) draw_oevent_list(win, &a->oevent_list); @@ -1884,9 +1900,11 @@ staticni void ged_input_cmd(Ged *a, Ged_input_cmd ev) { break; case Ged_input_cmd_step_forward: undo_history_push(&a->undo_hist, &a->field, a->tick_num); + a->guide.x = a->ged_cursor.x; + a->guide.y = a->ged_cursor.y; clear_and_run_vm(a->field.buffer, a->mbuf_r.buffer, a->field.height, a->field.width, a->tick_num, &a->oevent_list, - a->random_seed); + a->random_seed, &a->guide); ++a->tick_num; a->activity_counter += a->oevent_list.count; a->needs_remarking = true; From 1695f74aa4d0753e58bcedca87fe87e51f0f1da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigrid=20Hafl=C3=ADnud=C3=B3ttir?= Date: Tue, 5 May 2020 14:45:48 +0200 Subject: [PATCH 2/3] tui_main: advance_faketab would skip over too far in case column length is 7 chars, fix that --- tui_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tui_main.c b/tui_main.c index cdbaaf8..79f9ee8 100644 --- a/tui_main.c +++ b/tui_main.c @@ -449,7 +449,7 @@ staticni void advance_faketab(WINDOW *win, int offset_x, int tabstop) { getyx(win, y, x); getmaxyx(win, h, w); (void)h; - x = ((x + tabstop - 1) / tabstop) * tabstop + offset_x % tabstop; + x += tabstop - ((x - offset_x) % tabstop); if (w < 1) w = 1; if (x >= w) From da475625380675ab0379334716bbafb9121db344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigrid=20Hafl=C3=ADnud=C3=B3ttir?= Date: Tue, 5 May 2020 14:46:18 +0200 Subject: [PATCH 3/3] tui_main: use ops.h to build an array of guide items --- tui_main.c | 42 +++++++----------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/tui_main.c b/tui_main.c index 79f9ee8..ee6c489 100644 --- a/tui_main.c +++ b/tui_main.c @@ -7,6 +7,7 @@ #include "sysmisc.h" #include "term_util.h" #include "vmio.h" +#include "ops.h" #include #include @@ -2268,41 +2269,12 @@ static void push_opers_guide_msg(void) { char const *desc; }; static struct Guide_item items[] = { - {'A', "add", "Outputs sum of inputs."}, - {'B', "subtract", "Outputs difference of inputs."}, - {'C', "clock", "Outputs modulo of frame."}, - {'D', "delay", "Bangs on modulo of frame."}, - {'E', "east", "Moves eastward, or bangs."}, - {'F', "if", "Bangs if inputs are equal."}, - {'G', "generator", "Writes operands with offset."}, - {'H', "halt", "Halts southward operand."}, - {'I', "increment", "Increments southward operand."}, - {'J', "jumper", "Outputs northward operand."}, - {'K', "konkat", "Reads multiple variables."}, - {'L', "lesser", "Outputs smallest input."}, - {'M', "multiply", "Outputs product of inputs."}, - {'N', "north", "Moves Northward, or bangs."}, - {'O', "read", "Reads operand with offset."}, - {'P', "push", "Writes eastward operand."}, - {'Q', "query", "Reads operands with offset."}, - {'R', "random", "Outputs random value."}, - {'S', "south", "Moves southward, or bangs."}, - {'T', "track", "Reads eastward operand."}, - {'U', "uclid", "Bangs on Euclidean rhythm."}, - {'V', "variable", "Reads and writes variable."}, - {'W', "west", "Moves westward, or bangs."}, - {'X', "write", "Writes operand with offset."}, - {'Y', "jymper", "Outputs westward operand."}, - {'Z', "lerp", "Transitions operand to target."}, - {'*', "bang", "Bangs neighboring operands."}, - {'#', "comment", "Halts line."}, - // {'*', "self", "Sends ORCA command."}, - {':', "midi", "Sends MIDI note."}, - {'!', "cc", "Sends MIDI control change."}, - {'?', "pb", "Sends MIDI pitch bend."}, - // {'%', "mono", "Sends MIDI monophonic note."}, - {'=', "osc", "Sends OSC message."}, - {';', "udp", "Sends UDP message."}, +#define GUIDE_ITEM(_oper_char, _oper_name, _hr_name, _hr_desc) \ + {_oper_char, _hr_name, _hr_desc}, + + ALPHA_OPERATORS(GUIDE_ITEM) + UNIQUE_OPERATORS(GUIDE_ITEM) +#undef GUIDE_ITEM }; int w_desc = 0; for (Usz i = 0; i < ORCA_ARRAY_COUNTOF(items); ++i) {