AnalogTerm2: Add optional low bandwidth/bps simulation.
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 18 Apr 2023 00:35:44 +0000 (00:35 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 18 Apr 2023 00:35:44 +0000 (00:35 +0000)
mmsoftware/analogterm2/TODO.txt
mmsoftware/analogterm2/src/config.c
mmsoftware/analogterm2/src/config.h
mmsoftware/analogterm2/src/main.c

index aff34e1..f7acd43 100644 (file)
   This would allow applications like neovim using this VT520 feature to
   produce a faster blinking underline and bar cursor and a slower blinking
   block cursor.
+- Maybe also support cursor blinking delays where on != off.  A second
+  parameter could be added to the speed configuration sequence.  This would
+  be useful to have a mostly on cursor that occasionally briefly blinks just
+  to get noticeable.
 - On RPI when omxplayer is launched directly from analogterm2 and bash, it
   does not behave exactly like under xterm or urxvt: keys sent to omxplayer
   may either still be sent to analogterm2 or the terminal may be in another
   AnalogTerm.  Smooth scrolling could theoretically work with scroll
   regions (see TODO there)...  Then it may be possible to limit application
   input to display speed, either with XON/XOFF or slow reading...
-  Look at tcflow(3).
+  Look at tcflow(3).  It's possible that with signals on there's nothing else
+  to do than to delay until scrolling is done for I/O to flow properly.  The
+  new feature to limit the application input speed to emulate low bandwidth
+  suggests that is the case.
+  May be too slow if XShm is not available.
+  DECs that support smooth scrolling interestingly disable the cursor when
+  scrolling to immediately re-enable it after.  When the input bps is too
+  slow, the gradually appearing line can still be seen being written and a
+  little jump can be perceived between the lines.  When bps is high enough,
+  scrolling is smoother and steady.
 - Check termios(4) IMAXBEL and queue size, also reported by stty(1).
   This may allow to tweak interactive performance when a lot of application
   output happens.
   It seems that this is not used with modern terminfo/curses
   applications.  Xterm itself appears to only support it with
   certain fonts.
-- Jump/fast scroll, smooth/slow scroll (one line at a time).
-  One line at a time is now supported.  Without XShm performance was too low
-  to think about reimplementing smooth pixel-level scrolling that was added to
-  AnalogTerm 1.  With XShm this becomes a future possibility again.
 - h/l 1: Application Cursor Keys
 - Cursor color '\033]12;green\007' quite interestingly labels work.
   Numerics not always?
index 7dc0563..db5fdb4 100644 (file)
@@ -43,6 +43,7 @@ bool  cfg_sleep;
 bool   cfg_slowscroll;
 int    cfg_jumpscrolllines;
 int    cfg_leading;
+int    cfg_inputsleep, cfg_inputsleepskip;
 
 
 void
@@ -80,6 +81,9 @@ cfg_setdefaults(void)
        cfg_jumpscrolllines = JUMP_SCROLL_LINES;
 
        cfg_leading = EXTRA_LEADING;
+
+       cfg_inputsleep = INPUT_SLEEP;
+       cfg_inputsleepskip = INPUT_SLEEP_SKIP;
 }
 
 int 
index 6251af5..9eb5c4b 100644 (file)
@@ -264,6 +264,21 @@ extern int cfg_flashtime;
 
 
 /*
+ * Slow terminal simulation.  Sleeps a specified amount of microseconds before
+ * reading every character from the application/tty(4).  This will also affect
+ * user input that might buffer and only be processed slower.  Useful to debug
+ * applications to be more bandwidth efficient.  The skip setting is to read
+ * <n> characters before sleeping and is most useful to deal with schedulers
+ * that cannot provide accurately the number of requested ticks when sleeping.
+ */
+#define INPUT_SLEEP            0
+#define INPUT_SLEEP_SKIP       0
+
+extern int cfg_inputsleep;
+extern int cfg_inputsleepskip;
+
+
+/*
  * The XShm extention allows to accelerate graphics when the client is running
  * on the same system as the X11 server.
  */
index 60b6b08..41e7564 100644 (file)
@@ -37,6 +37,8 @@ int                   main(int, char **, char **);
 static const char      *progname = "";
 static Time            lastexpose = -1;
 
+static int             inputsleepskip = 0;
+
 
 
 static bool
@@ -176,7 +178,8 @@ usage(void)
            "\nUsage: %s [-8|-u] [-w <cols>] [-h <rows>] [-E <n>] [-s]\n"
            "    [-C <color>] [-c] [-W] [-b] [-r <ms>] [-B <ticks>] [-j <n>]\n"
            "    [-P] [-m <mode>] [-M] [-d] [-D] [-S] [-p <parameters>]\n"
-           "    [-l <pixels>] [-f <delay>] [-e <command> [<arguments>]]\n\n"
+           "    [-l <pixels>] [-f <delay>] [-z <ms>] [-Z <skip>] \n"
+           "    [-e <command> [<arguments>]]\n\n"
            "Where:\n"
            " -8 / -u - 8-bit mode (Latin-1), unicode+UTF-8.  8-bit mode is\n"
            "           automatically enabled by default if the LANG\n"
@@ -221,6 +224,16 @@ usage(void)
            " -f - Number of frames to keep reverse video on for the flash\n"
            "      of the visual bell.  May not be visible with very low\n"
            "      values.  Also depends on -r.\n"
+           " -z - Slow bandwidth/bps simulation.  Sleep the specified\n"
+           "      number of milliseconds before reading each byte from the\n"
+           "      application tty(4).  Will also affect the rate of input\n"
+           "      processing causing the queue to grow.  Also see -Z.\n"
+           "      Useful to audit/optimize applications or as a fun effect.\n"
+           "      Disabling jump scrolling will affect the behavior, see -r\n"
+           "      and -j.\n"
+           " -Z - If -z is enabled, specify the number of bytes to read\n"
+           "      before sleeping.  Useful when the scheduler cannot sleep\n"
+           "      for short enough delays.\n"
            " -e - Execute command and its arguments instead of $SHELL.\n"
            "      Must be the last AnalogTerm2 argument if used, because\n"
            "      other arguments will be passed to the command.\n"
@@ -265,7 +278,7 @@ main(int argc, char **argv, char **envp)
 
        progname = strdup(argv[0]);
        while ((ch = getopt(argc, argv,
-           "?8uw:h:E:scC:Wr:bB:j:Pm:MdDSp:l:f:e:")) != -1) {
+           "?8uw:h:E:scC:Wr:bB:j:Pm:MdDSp:l:f:z:Z:e:")) != -1) {
                switch (ch) {
                case '8':
                        cfg_unicode = false;
@@ -358,6 +371,14 @@ main(int argc, char **argv, char **envp)
                        if ((i = atoi(optarg)) >= 0 && i <= 100)
                                cfg_flashtime = i;
                        break;
+               case 'z':
+                       if ((i = atoi(optarg)) > -1 && i <= 100000)
+                               cfg_inputsleep = i;
+                       break;
+               case 'Z':
+                       if ((i = atoi(optarg)) > -1)
+                               cfg_inputsleepskip = inputsleepskip = i;
+                       break;
                case 'e':
                        {
                                int l;
@@ -514,12 +535,24 @@ endopt:
                        break;
                }
                if ((pfd[1].revents & POLLIN) != 0) {
+                       size_t rbufsize = RBUF_SIZE;
+
                        /* For interactive performance */
                        if (!x11_process(screen, ttys, state)) {
                                warnx("x11_process() false");
                                break;
                        }
-                       if ((size = read(ttys->ptyfd, ttys->rbuf, RBUF_SIZE))
+
+                       /* Low bandwidth simulation */
+                       if (cfg_inputsleep > 0) {
+                               rbufsize = 1;
+                               if (--inputsleepskip < 1) {
+                                       inputsleepskip = cfg_inputsleepskip;
+                                       (void)usleep(cfg_inputsleep);
+                               }
+                       }
+
+                       if ((size = read(ttys->ptyfd, ttys->rbuf, rbufsize))
                            == -1 && errno != EAGAIN && errno != EINTR) {
                                warn("read(shell) error");
                                break;