shithub: orca

Download patch

ref: 62bad19cae1b990006ab28c3f3348816cd502044
parent: 1758bfee21285b04b608f2bd7e415812ab802ac2
author: cancel <cancel@cancel.fm>
date: Wed Jan 1 18:25:12 EST 2020

Change output activity indicator to be a visual counter

This changes the output meter from a VU/peak-like meter of recent
activity to an incrementing visual counter. I believe this is an
improvement, because it's now easier to discern output activity across a
broader range of activity levels.

--- a/tui_main.c
+++ b/tui_main.c
@@ -433,22 +433,54 @@
 
 Usz undo_history_count(Undo_history* hist) { return hist->count; }
 
-void print_meter(WINDOW* win, float meter_level) {
-  enum { Segments = 7 };
-  int segs = (int)(meter_level * (float)Segments + 0.5f);
-  if (segs < 0)
-    segs = 0;
-  else if (segs > Segments)
-    segs = Segments;
+void print_activity_indicator(WINDOW* win, Usz activity_counter) {
+  // 7 segments that can each light up as Colors different colors.
+  // This gives us Colors^Segments total configurations.
+  enum { Segments = 7, Colors = 4 };
+  Usz states = 1; // calculate Colors^Segments
+  for (Usz i = 0; i < Segments; ++i)
+    states *= Colors;
+  // Wrap the counter to the range of displayable configurations.
+  Usz val = activity_counter % states;
+  chtype lamps[Colors];
+#if 1 // Appearance where segments are always lit
+  lamps[0] = ACS_HLINE | fg_bg(C_black, C_natural) | A_bold;
+  lamps[1] = ACS_HLINE | fg_bg(C_white, C_natural) | A_normal;
+  lamps[2] = ACS_HLINE | A_bold;
+  lamps[3] = lamps[1];
+#elif 0 // Brighter appearance where segments are always lit
+  lamps[0] = ACS_HLINE | fg_bg(C_black, C_natural) | A_bold;
+  lamps[1] = ACS_HLINE | A_normal;
+  lamps[2] = ACS_HLINE | A_bold;
+  lamps[3] = lamps[1];
+#else // Appearance where segments can turn off completely
+  lamps[0] = ' ';
+  lamps[1] = ACS_HLINE | fg_bg(C_black, C_natural) | A_bold;
+  lamps[2] = ACS_HLINE | A_normal;
+  lamps[3] = lamps[1];
+#endif
   chtype buffer[Segments];
-  int i = 0;
-  for (; i < segs; ++i) {
-    buffer[i] = (i % 2 ? ACS_PLUS : ACS_HLINE) | A_REVERSE;
+  for (Usz i = 0; i < Segments; ++i) {
+    // Instead of a left-to-right, straightforward ascending least-to-most
+    // significant digits display, we'll display it as a spiral.
+    Usz j = i % 2 ? (6 - i / 2) : (i / 2);
+    buffer[j] = lamps[val % Colors];
+    val = val / Colors;
   }
-  for (; i < Segments; ++i) {
-    buffer[i] = ACS_HLINE | A_DIM;
-  }
   waddchnstr(win, buffer, Segments);
+  // If you want to see what various combinations of colors and attributes look
+  // like in different terminals.
+#if 0
+  waddch(win, 'a' | fg_bg(C_black, C_natural) | A_dim);
+  waddch(win, 'b' | fg_bg(C_black, C_natural) | A_normal);
+  waddch(win, 'c' | fg_bg(C_black, C_natural) | A_bold);
+  waddch(win, 'd' | A_dim);
+  waddch(win, 'e' | A_normal);
+  waddch(win, 'f' | A_bold);
+  waddch(win, 'g' | fg_bg(C_white, C_natural) | A_dim);
+  waddch(win, 'h' | fg_bg(C_white, C_natural) | A_normal);
+  waddch(win, 'i' | fg_bg(C_white, C_natural) | A_bold);
+#endif
 }
 
 void draw_hud(WINDOW* win, int win_y, int win_x, int height, int width,
@@ -455,13 +487,13 @@
               const char* 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,
-              float meter_level) {
+              Usz activity_counter) {
   (void)height;
   (void)width;
   wmove(win, win_y, win_x);
   wprintw(win, "%dx%d\t%d/%d\t%df\t%d\t", (int)field_w, (int)field_h,
           (int)ruler_spacing_x, (int)ruler_spacing_y, (int)tick_num, (int)bpm);
-  print_meter(win, meter_level);
+  print_activity_indicator(win, activity_counter);
   wmove(win, win_y + 1, win_x);
   wprintw(win, "%d,%d\t%d:%d\t", (int)ged_cursor->x, (int)ged_cursor->y,
           (int)ged_cursor->w, (int)ged_cursor->h);
@@ -782,7 +814,7 @@
   Usz random_seed;
   Usz drag_start_y;
   Usz drag_start_x;
-  float meter_level;
+  Usz activity_counter;
   int win_h;
   int win_w;
   int grid_h;
@@ -822,7 +854,7 @@
   a->random_seed = init_seed;
   a->drag_start_y = 0;
   a->drag_start_x = 0;
-  a->meter_level = 0.0f;
+  a->activity_counter = 0;
   a->win_h = 0;
   a->win_w = 0;
   a->grid_h = 0;
@@ -1074,15 +1106,6 @@
   }
 }
 
-ORCA_FORCE_INLINE
-static float float_clamp(float a, float low, float high) {
-  if (a < low)
-    return low;
-  if (a > high)
-    return high;
-  return a;
-}
-
 void ged_reset_clock(Ged* a) { a->clock = stm_now(); }
 
 void ged_do_stuff(Ged* a) {
@@ -1090,8 +1113,7 @@
   Oosc_dev* oosc_dev = a->oosc_dev;
   Midi_mode const* midi_mode = a->midi_mode;
   double secs = stm_sec(stm_since(a->clock));
-  a->meter_level -= (float)secs;
-  a->meter_level = float_clamp(a->meter_level, 0.0f, 1.0f);
+  (void)secs; // unused, was previously used for activity meter decay
   if (!a->is_playing)
     return;
   bool do_play = false;
@@ -1143,9 +1165,8 @@
     if (count > 0) {
       send_output_events(oosc_dev, midi_mode, a->bpm, &a->susnote_list,
                          a->oevent_list.buffer, count);
+      a->activity_counter += count;
     }
-    a->meter_level += (float)count * 0.2f;
-    a->meter_level = float_clamp(a->meter_level, 0.0f, 1.0f);
     // note for future: sustained note deadlines may have changed due to note
     // on. will need to update stored deadline in memory if
     // ged_apply_delta_secs isn't called again immediately after ged_do_stuff.
@@ -1246,7 +1267,7 @@
     draw_hud(win, win_h - Hud_height, 0, 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->meter_level);
+             a->input_mode, a->activity_counter);
   }
   if (a->draw_event_list) {
     draw_oevent_list(win, &a->oevent_list);
@@ -1653,6 +1674,7 @@
     orca_run(a->field.buffer, a->mbuf_r.buffer, a->field.height, a->field.width,
              a->tick_num, &a->oevent_list, a->piano_bits, a->random_seed);
     ++a->tick_num;
+    a->activity_counter += a->oevent_list.count;
     a->piano_bits = ORCA_PIANO_BITS_NONE;
     a->needs_remarking = true;
     a->is_draw_dirty = true;
@@ -1661,7 +1683,6 @@
     if (a->is_playing) {
       ged_stop_all_sustained_notes(a);
       a->is_playing = false;
-      a->meter_level = 0.0f;
       send_control_message(a->oosc_dev, "/orca/stopped");
     } else {
       undo_history_push(&a->undo_hist, &a->field, a->tick_num);