wvdakker / gtkterm

GTKTerm: A GTK+ Serial Port Terminal
GNU General Public License v3.0
104 stars 35 forks source link

Ability to freeze the screen, ie halting the display of incoming data ? #51

Open linuxguy123 opened 2 years ago

linuxguy123 commented 2 years ago

Hi.

I've used GTKTerm for years for microcontroller development. I generally use it for monitoring the output of a serial port and for simple debugging.

One of the things I've always missed on GTKTerm is the ability to freeze the display of the incoming data so that I could scroll back in history and look at something while the micro is still outputting data into a buffer. Then when I unfreeze it, it would resume displaying data, starting with the data in the buffer.

I've looked at the code and have a few questions.

1) Buffer "c" as used in serial.c is a non circular buffer between the serial port buffer (14 bytes or so) and the main program display ?

2) put_chars reads incoming data from buffer "c" to puts it in outbuffer which is then displayed by vte ?

3) re: read(serial_port_fd, c, BUFFER_RECEPTION) - the data read is put into 'c' always at the beginning of buffer 'c'. There is no way to append a second read() onto existing data already in buffer 'c' ?

Thanks

wvdakker commented 2 years ago

Hi,

Thanks for your feedback. Concerning pausing the bufferoutput. Is it an option to close the port? We can add the pause feature in the roadmap for 2.0.

1: Yes it is a 8K buffer between port and output to the terminal

2: Correct

3: Correct. In 2.0 the output is appended to the buffer. The buffer moves up in pages. The buffer is completely rewritten in 2.0.

linuxguy123 commented 2 years ago

Thanks for the reply.

I'm willing to write the code and submit the diffs, if you give me a little direction.

Closing the port is not an option as reopening it will reset the micro in my case. (ESP32) There are other reasons not to want to do this, like with a debugger, where closing the port will shut down the debugging process and reopening the port would reinit the debugger.

I'm thinking the easiest way to do this would be modify the c buffer object to be circular so that new reads aren't appended to the start of the buffer thus over writing previous data that may not have been written out yet.

Then to pause displaying the new data, we could just freeze put_chars.

Something like this:

gboolean Lis_port(GIOChannel* src, GIOCondition cond, gpointer data)
{

    gint bytes_read;  //bytes read from the serial port put into buffer "c"
    gint bytes_waiting; // bytes sitting in buffer c waiting to be displayed  
    static gchar c[BUFFER_RECEPTION];
    guint i;

    bytes_read = BUFFER_RECEPTION;

    while(bytes_read == BUFFER_RECEPTION)
    {
        bytes_read = read(serial_port_fd, c, BUFFER_RECEPTION);

        // add bytes read to bytes waiting
        bytes_waiting += bytes_read;

        if((bytes_waiting > 0)&&(!frozen)) // frozen is the global var that controls this
        {
            // from buffer.c, writes to outbuffer 
            put_chars(c, bytes_waiting, config.crlfauto); 

            if(config.car != -1 && waiting_for_char == TRUE)
            {
                i = 0;
                while(i < bytes_waiting)
                {
                    if(c[i] == config.car)
                    {
                        waiting_for_char = FALSE;
                        add_input();
                        i = bytes_waiting;
                    }
                    i++;
                }
            }
        }
        else if(bytes_waiting == -1)
        {
            if(errno != EAGAIN)
                perror(config.port);
        }

    }

    return TRUE;
}

BTW, I find your code to be well written but a few more high level comments would be nice. For example, a short descriptor above each function definition (or declaration) that states what the function does. Often you can tell by the name, but sometimes it is not so obvious. put_chars, for example. "Put_chars transfers the data from c buffer to output, correcting for CR and LF as necessary. VTE displays the data in output. c is the raw read buffer for the serial io."

More high level comments would make it a lot easier for someone not knowledgeable with the program's structure to get up to speed quickly.

I've used GTKTerm for years. Thanks for writing it and keep up the great work.

linuxguy123 commented 2 years ago

The buffer is completely rewritten in 2.0.

I wasn't aware that there is a 2.0 version. When are you planning to ship it ?

$ git show
commit d227a75045664aa0b25247cdaaf384e490445225 (HEAD -> master, tag: 1.2.1, origin/master, origin/HEAD)
wvdakker commented 2 years ago

There is a gtk4 branch.

On Wed, 2022-10-19 at 08:06 -0700, linuxguy123 wrote:

The buffer is completely rewritten in 2.0. I wasn't aware that there is a 2.0 version. $ git show commit d227a75 (HEAD -> master, tag: 1.2.1, origin/master, origin/HEAD) — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

linuxguy123 commented 2 years ago

When are you planning to ship version 2.0 ? Is it ready for testing right now ?

linuxguy123 commented 2 years ago

Is 1.9.1 the lastest code ? Or is there something more recent ?

linuxguy123 commented 2 years ago

In 1.9.1 you have this code:

/** Send signal to buffer when new data is arrived */
    g_signal_emit (self, gtkterm_signals[SIGNAL_GTKTERM_SERIAL_DATA_RECEIVED], 0, data);

/** Restart listener */
    g_input_stream_read_bytes_async (priv->input_stream,
                                     GTKTERM_SERIAL_PORT_RECEIVE_BUFFER_SIZE,
                                     G_PRIORITY_DEFAULT,
                                     priv->cancellable,
                                     gtkterm_serial_port_serial_data_received,
                                     self);

If the buffer will accept new data without over writing old data, could the freeze be accomplished by delaying the call to restart the listener ?

wvdakker commented 2 years ago

Well you can always test :) The core functionality is ready. The menu options, filetransfer, macros not yet.

On Wed, 2022-10-19 at 08:15 -0700, linuxguy123 wrote:

When are you planning to ship version 2.0 ? Is it ready for testing right now ? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

wvdakker commented 2 years ago

The gtk4 branch has the latest code published. Got local some changes.

On Wed, 2022-10-19 at 08:18 -0700, linuxguy123 wrote:

Is 1.9.1 the lastest code ? Or is there something more recent ? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

wvdakker commented 2 years ago

How it can be done is a 'buffer_hold' flag. This can be set in the menu. Only thing the flag does is not writing into the buffer, logging should normaly continue.

That could be implemented in 2.0

On Wed, 2022-10-19 at 08:26 -0700, linuxguy123 wrote:

In 1.9.1 you have this call: /* Send signal to buffer when new data is arrived / g_signal_emit (self, gtkterm_signals[SIGNAL_GTKTERM_SERIAL_DATA_RECEIVED], 0, data);

/* Restart listener / g_input_stream_read_bytes_async (priv->input_stream, GTKTERM_SERIAL_PORT_RECEIVE_BUFFER_SIZE, G_PRIORITY_DEFAULT, priv->cancellable, gtkterm_serial_port_serial_data_received, self);

If the buffer will accept new data without over writing old data, could the freeze be accomplished by delaying the call to restart the listener ? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

wvdakker commented 2 years ago

Yes that could be a possible solution.

On Wed, 2022-10-19 at 07:58 -0700, linuxguy123 wrote:

Thanks for the reply. I'm willing to write the code and submit the diffs, if you give me a little direction. Closing the port is not an option as reopening it will reset the micro in my case. (ESP32) There are other reasons not to want to do this, like with a debugger, where closing the port will shut down the debugging process and reopening the port would reinit the debugger. I'm thinking the easiest way to do this would be modify the buffer object to be circular to that new reads aren't appended to the start of the buffer thus over writing previous data that may not have been written out yet. Then to pause displaying the new data, we could just freeze put_chars. Something like this. gboolean Lis_port(GIOChannel* src, GIOCondition cond, gpointer data) {

gint bytes_read; //bytes read from the serial port put into buffer "c" gint bytes_waiting; // bytes sitting in buffer c waiting to be displayed
static gchar c[BUFFER_RECEPTION]; guint i;

bytes_read = BUFFER_RECEPTION;

while(bytes_read == BUFFER_RECEPTION) { bytes_read = read(serial_port_fd, c, BUFFER_RECEPTION);

  // add bytes read to bytes waiting
  bytes_waiting += bytes_read;

  if((bytes_waiting > 0)&&(!frozen)) // frozen is the global var that controls this
  {
      // from buffer.c, writes to outbuffer 
      put_chars(c, bytes_waiting, config.crlfauto); 

      if(config.car != -1 && waiting_for_char == TRUE)
      {
          i = 0;
          while(i < bytes_waiting)
          {
              if(c[i] == config.car)
              {
                  waiting_for_char = FALSE;
                  add_input();
                  i = bytes_waiting;
              }
              i++;
          }
      }
  }
  else if(bytes_waiting == -1)
  {
      if(errno != EAGAIN)
          perror(config.port);
  }

}

return TRUE; } BTW, I find your code to be well written but a few more high level comments would be nice. For example, a short descriptor above each function definition (or declaration) that states what the function does. Often you can tell by the name, but sometimes it is not so obvious. put_chars, for example. "Put_chars transfers the data from c buffer to output, correcting for CR and LF as necessary. VTE displays the data in output. c is the raw read buffer for the serial io." — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>