From a4ec4b272b2eae527f68cbd40488a7805dc5367b Mon Sep 17 00:00:00 2001 From: Xiao Pan Date: Sun, 6 Apr 2025 17:27:44 -0700 Subject: Integrate with gtk --- remote_plot.c | 385 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 244 insertions(+), 141 deletions(-) (limited to 'remote_plot.c') diff --git a/remote_plot.c b/remote_plot.c index b1cb2a6..8f89e62 100644 --- a/remote_plot.c +++ b/remote_plot.c @@ -2,6 +2,7 @@ // https://api.libssh.org/stable/libssh_tutorial.html // https://api.libssh.org/stable/libssh_tutor_guided_tour.html // plplot example 17 +// plplot example ext-cairo-test.c #include #include @@ -22,6 +23,8 @@ #include #include +#include + // very small also works, just transfter delays, I test accelerometer data is // like 15782 which is 7 bytes consider newline and \0? #define MAX_XFER_BUF_SIZE 7 @@ -30,143 +33,78 @@ static PLINT pl_errcode; static char errmsg[160]; -int sftp_read_sync(ssh_session session, sftp_session sftp) +typedef struct { + ssh_session session; + sftp_session sftp; + PLINT id1; + PLFLT t[10]; + PLFLT buffer[10]; + GtkWidget *area; +}DATA; + +static gboolean sftp_read_sync(gpointer user_data) + //int sftp_read_sync(ssh_session session, sftp_session sftp) { + //printf("sftp_read_sync begin\n"); + DATA *data=user_data; + int access_type; sftp_file file; char buffer[MAX_XFER_BUF_SIZE]; int nbytes, rc; access_type = O_RDONLY; - PLINT id1, autoy, acc; - PLFLT ymin, ymax, xlab, ylab; - PLFLT t, tmin, tmax, tjump; - PLINT colbox, collab, colline[4], styline[4]; - PLCHAR_VECTOR legline[4]; - - // If db is used the plot is much more smooth. However, because of the - // async X behaviour, one does not have a real-time scripcharter. - // This is now disabled since it does not significantly improve the - // performance on new machines and makes it difficult to use this - // example non-interactively since it requires an extra pleop call after - // each call to plstripa. - // - //plsetopt("db", ""); - //plsetopt("np", ""); - - // User sets up plot completely except for window and data - // Eventually settings in place when strip chart is created will be - // remembered so that multiple strip charts can be used simultaneously. - // - - // Specify some reasonable defaults for ymin and ymax - // The plot will grow automatically if needed (but not shrink) - - ymin = -0.1; - ymax = 0.1; - - // Specify initial tmin and tmax -- this determines length of window. - // Also specify maximum jump in t - // This can accomodate adaptive timesteps - - tmin = 0.; - tmax = 10.; - tjump = 0.3; // percentage of plot to jump - - // Axes options same as plbox. - // Only automatic tick generation and label placement allowed - // Eventually I'll make this fancier - - colbox = 1; - collab = 3; - styline[0] = colline[0] = 2; // pens color and line style - styline[1] = colline[1] = 3; - styline[2] = colline[2] = 4; - styline[3] = colline[3] = 5; - - legline[0] = "in_accel_z_raw"; // pens legend - legline[1] = "not_used"; - legline[2] = "not_used"; - legline[3] = "not_used"; - - xlab = 0.; ylab = 0.25; // legend position - - autoy = 1; // autoscale y - acc = 1; // don't scrip, accumulate - - // Initialize plplot - - plinit(); - - pladv( 0 ); - plvsta(); - - // Register our error variables with PLplot - // From here on, we're handling all errors here - - plsError( &pl_errcode, errmsg ); - - plstripc( &id1, "bcnst", "bcnstv", - tmin, tmax, tjump, ymin, ymax, - xlab, ylab, - autoy, acc, - colbox, collab, - colline, styline, legline, - "t", "", "Strip chart demo" ); - - if ( pl_errcode ) - { - fprintf( stderr, "%s\n", errmsg ); - exit( 1 ); - } - - // Let plplot handle errors from here on - - plsError( NULL, NULL ); - - autoy = 0; // autoscale y - acc = 1; // accumulate - // This is to represent a loop over time // Let's try a random walk process - for (t=0;;t++) { - file = sftp_open(sftp, "/sys/bus/iio/devices/iio:device2/in_accel_z_raw", - access_type, 0); - if (file == NULL) { - fprintf(stderr, "Can't open file for reading: %s\n", - ssh_get_error(session)); + file = sftp_open(data->sftp, "/sys/bus/iio/devices/iio:device2/in_accel_z_raw", + access_type, 0); + if (file == NULL) { + fprintf(stderr, "Can't open file for reading: %s\n", + ssh_get_error(data->session)); + return SSH_ERROR; + } + + for(int i=0;i<9;i++) + data->buffer[i]=data->buffer[i+1]; + + for (;;) { + nbytes = sftp_read(file, buffer, sizeof(buffer)); + if (nbytes == 0) { + break; // EOF + } else if (nbytes < 0) { + fprintf(stderr, "Error while reading file: %s\n", + ssh_get_error(data->session)); + sftp_close(file); return SSH_ERROR; } - for (;;) { - nbytes = sftp_read(file, buffer, sizeof(buffer)); - if (nbytes == 0) { - break; // EOF - } else if (nbytes < 0) { - fprintf(stderr, "Error while reading file: %s\n", - ssh_get_error(session)); - sftp_close(file); - return SSH_ERROR; - } - - //printf("%s",buffer); - //printf("%d\n",atoi(buffer)); - plstripa( id1, 0, t, atof(buffer)); - } + //printf("buffer %s",buffer); + //printf("buffer int %d\n",atoi(buffer)); + //printf("id1 %d\n",data->id1); + //printf("t %f\n",data->t[9]); + //printf("before sftp_read_sync plstripa\n"); + data->buffer[9]=atof(buffer); + //printf("after sftp_read_sync plstripa\n"); } rc = sftp_close(file); if (rc != SSH_OK) { fprintf(stderr, "Can't close the read file: %s\n", - ssh_get_error(session)); + ssh_get_error(data->session)); return rc; } - plstripd( id1 ); - plend(); + for(int i=0;i<10;i++) + data->t[i]++; + //printf("sftp_read_sync end\n"); - return SSH_OK; + gtk_widget_queue_draw(data->area); + + //return SSH_OK; + // must return G_SOURCE_CONTINUE to keep polling + // return G_SOURCE_REMOVE to stop + return G_SOURCE_CONTINUE; } // https://api.libssh.org/stable/libssh_tutor_guided_tour.html @@ -257,73 +195,238 @@ int verify_knownhost(ssh_session session) return 0; } -int main(void) +static void draw_function (GtkDrawingArea *area, + cairo_t *cr, + int width, + int height, + gpointer user_data) { - ssh_session my_ssh_session; - sftp_session sftp; + //printf("draw begin\n"); + DATA *data=user_data; + + PLINT autoy, acc; + PLFLT ymin, ymax, xlab, ylab; + PLFLT tmin, tmax, tjump; + PLINT colbox, collab, colline[4], styline[4]; + PLCHAR_VECTOR legline[4]; + + // If db is used the plot is much more smooth. However, because of the + // async X behaviour, one does not have a real-time scripcharter. + // This is now disabled since it does not significantly improve the + // performance on new machines and makes it difficult to use this + // example non-interactively since it requires an extra pleop call after + // each call to plstripa. + // + //plsetopt("db", ""); + //plsetopt("np", ""); + + // User sets up plot completely except for window and data + // Eventually settings in place when strip chart is created will be + // remembered so that multiple strip charts can be used simultaneously. + // + + // Specify some reasonable defaults for ymin and ymax + // The plot will grow automatically if needed (but not shrink) + + ymin = -0.1; + ymax = 0.1; + + // Specify initial tmin and tmax -- this determines length of window. + // Also specify maximum jump in t + // This can accomodate adaptive timesteps + + tmin = 0.; + tmax = 10.; + tjump = 0.3; // percentage of plot to jump + + // Axes options same as plbox. + // Only automatic tick generation and label placement allowed + // Eventually I'll make this fancier + + colbox = 1; + collab = 3; + styline[0] = colline[0] = 2; // pens color and line style + styline[1] = colline[1] = 3; + styline[2] = colline[2] = 4; + styline[3] = colline[3] = 5; + + legline[0] = "in_accel_z_raw"; // pens legend + legline[1] = "not_used"; + legline[2] = "not_used"; + legline[3] = "not_used"; + + xlab = 0.; ylab = 0.25; // legend position + + autoy = 1; // autoscale y + acc = 1; // don't scrip, accumulate + + // Initialize plplot + + plsdev( "extcairo" ); + plinit(); + pl_cmd( PLESC_DEVINIT, cr ); + + pladv( 0 ); + plvsta(); + + // Register our error variables with PLplot + // From here on, we're handling all errors here + + plsError( &pl_errcode, errmsg ); + + //plstripc( &(data->id1), "bcnst", "bcnstv", + plstripc( &(data->id1), "bcnst", "bcnstv", + tmin, tmax, tjump, ymin, ymax, + xlab, ylab, + autoy, acc, + colbox, collab, + colline, styline, legline, + "t", "", "Strip chart demo" ); + + if ( pl_errcode ) + { + fprintf( stderr, "%s\n", errmsg ); + exit( 1 ); + } + + // Let plplot handle errors from here on + + plsError( NULL, NULL ); + + autoy = 0; // autoscale y + acc = 1; // accumulate + + for(int i=0;i<10;i++) + { + //printf("t%d %f\n",i,data->t[i]); + //printf("buffer%d %f\n",i,data->buffer[i]); + plstripa( data->id1, 0, data->t[i], data->buffer[i]); + } + + //printf("before pl free\n"); + plstripd( data->id1 ); + plend(); + //printf("draw done\n"); +} + +static void print_hello (GtkWidget *widget, gpointer user_data) +{ + g_print ("Hello World\n"); +} + +static void activate (GtkApplication *app, gpointer user_data) +{ + DATA *data=user_data; + GtkWidget *window; + data->area = gtk_drawing_area_new (); + GtkWidget *button; + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL,1); + + window = gtk_application_window_new (app); + gtk_window_set_title (GTK_WINDOW (window), "remote_plot"); + gtk_window_set_default_size (GTK_WINDOW (window), 1000, 1000); + + gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (data->area), 600); + gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (data->area), 600); + gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (data->area), + draw_function, + user_data, NULL); + + button = gtk_button_new_with_label ("Hello World"); + g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL); + + gtk_box_append(GTK_BOX(box), button); + gtk_box_append(GTK_BOX(box), data->area); + gtk_window_set_child (GTK_WINDOW (window), box); + + gtk_window_present (GTK_WINDOW (window)); + + g_timeout_add(50,sftp_read_sync,user_data); + //printf("after g_timeout_add\n"); +} + +int main (int argc, char **argv) +{ + DATA data; + //ssh_session session; + //sftp_session sftp; int rc; + GtkApplication *app; + int status; + + for(int i=0;i<10;i++) + { + data.t[i]=i; + data.buffer[i]=0; + } + // Open session and set options - my_ssh_session = ssh_new(); - if (my_ssh_session == NULL) + data.session = ssh_new(); + if (data.session == NULL) exit(-1); - ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "10.0.0.7"); + ssh_options_set(data.session, SSH_OPTIONS_HOST, "10.0.0.7"); // Connect to server - rc = ssh_connect(my_ssh_session); + rc = ssh_connect(data.session); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to 10.0.0.7: %s\n", - ssh_get_error(my_ssh_session)); - ssh_free(my_ssh_session); + ssh_get_error(data.session)); + ssh_free(data.session); exit(-1); } // Verify the server's identity // For the source code of verify_knownhost(), check previous example - if (verify_knownhost(my_ssh_session) < 0) + if (verify_knownhost(data.session) < 0) { - ssh_disconnect(my_ssh_session); - ssh_free(my_ssh_session); + ssh_disconnect(data.session); + ssh_free(data.session); exit(-1); } // Authenticate ourselves // https://api.libssh.org/stable/libssh_tutor_authentication.html - rc = ssh_userauth_publickey_auto(my_ssh_session, NULL, NULL); + rc = ssh_userauth_publickey_auto(data.session, NULL, NULL); if (rc != SSH_AUTH_SUCCESS) { fprintf(stderr, "Error authenticating with key: %s\n", - ssh_get_error(my_ssh_session)); - ssh_disconnect(my_ssh_session); - ssh_free(my_ssh_session); + ssh_get_error(data.session)); + ssh_disconnect(data.session); + ssh_free(data.session); exit(-1); } - sftp = sftp_new(my_ssh_session); - if (sftp == NULL) + data.sftp = sftp_new(data.session); + if (data.sftp == NULL) { fprintf(stderr, "Error allocating SFTP session: %s\n", - ssh_get_error(my_ssh_session)); + ssh_get_error(data.session)); return SSH_ERROR; } - rc = sftp_init(sftp); + rc = sftp_init(data.sftp); if (rc != SSH_OK) { fprintf(stderr, "Error initializing SFTP session: code %d.\n", - sftp_get_error(sftp)); - sftp_free(sftp); + sftp_get_error(data.sftp)); + sftp_free(data.sftp); return rc; } - sftp_read_sync(my_ssh_session,sftp); + app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect (app, "activate", G_CALLBACK (activate), &data); + status = g_application_run (G_APPLICATION (app), argc, argv); + g_object_unref (app); + + //printf("before ssh free\n"); - ssh_disconnect(my_ssh_session); - ssh_free(my_ssh_session); + ssh_disconnect(data.session); + ssh_free(data.session); // Segmentation fault (core dumped) error, why? maybe double free? so no free is ok? //sftp_free(sftp); - return 0; + return status; } -- cgit v1.2.3-70-g09d2