Re: Capture console app output into texview?
Hi, thanks a lot for that explanation. I'll try to combine this into the code from Dov. Till Am Samstag 21 November 2009 schrieb Artur Galjamov: Hi, After exec(), child clib's startup routine determines buffering mode for stdout (i.e. calls fdopen(1, w+)). You can setup pseudo-terminal instead of pipe, to make child's stdout line-buffered. optimistic snippet: = #include fcntl.h #include stdio.h #include stdlib.h #include unistd.h int main(int argc, char *argv[]) { int master_fd, slave_fd; FILE*master_file, *slave_file; char buf[80], *device; master_fd = posix_openpt(O_RDWR | O_NOCTTY); grantpt(master_fd); unlockpt(master_fd); slave_fd = open(device = ptsname(master_fd), O_RDWR | O_NOCTTY); printf(slave device: %s\n, device); master_file = fdopen(master_fd, r); slave_file = fdopen(slave_fd, w+); if (fork()) { fclose(slave_file); while (fgets(buf, sizeof(buf), master_file)) printf(parent got: %s, buf); } else { // child fclose(master_file); for (int i = 0; i 500; i++) { sleep(1); fprintf(slave_file, child's data (%d)\n, i); } } return 0; } = 21.11.09, 09:39, Till Harbaum / Lists li...@harbaum.org: Hi, thanks again for that hint. Unfortunately adding /* switch to line buffered mode */ if(setvbuf(fh, NULL, _IOLBF, 0)) perror(setvbuf(_IOLBF)); to the program posted by Dov doesn't change anything. Are there limitations on changing the buffer mode? E.g. only the transmitter side can do that? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
Hi, thanks again for that hint. Unfortunately adding /* switch to line buffered mode */ if(setvbuf(fh, NULL, _IOLBF, 0)) perror(setvbuf(_IOLBF)); to the program posted by Dov doesn't change anything. Are there limitations on changing the buffer mode? E.g. only the transmitter side can do that? Till Am Freitag 20 November 2009 schrieb David Nečas: Terminals are normaly line-buffered while pipes are block-buffered, see setvbuf(3) for some info. So the buffering behaviour differs depending on where the output goes. ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
On Sat, Nov 21, 2009 at 09:39:49AM +0100, Till Harbaum / Lists wrote: thanks again for that hint. Unfortunately adding /* switch to line buffered mode */ if(setvbuf(fh, NULL, _IOLBF, 0)) perror(setvbuf(_IOLBF)); to the program posted by Dov doesn't change anything. Are there limitations on changing the buffer mode? E.g. only the transmitter side can do that? The buffering is a feature of FILE* streams and is done in libc on both sides. So you effectively get the larger of the two buffers set by both sides on the reading side (ordering the sizes none line full). If the writer only sends the data to the pipe in full blocks there's nothing you can with it on the reading side. At least that's how I understand it. Yeti ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
Hi, After exec(), child clib's startup routine determines buffering mode for stdout (i.e. calls fdopen(1, w+)). You can setup pseudo-terminal instead of pipe, to make child's stdout line-buffered. optimistic snippet: = #include fcntl.h #include stdio.h #include stdlib.h #include unistd.h int main(int argc, char *argv[]) { int master_fd, slave_fd; FILE*master_file, *slave_file; char buf[80], *device; master_fd = posix_openpt(O_RDWR | O_NOCTTY); grantpt(master_fd); unlockpt(master_fd); slave_fd = open(device = ptsname(master_fd), O_RDWR | O_NOCTTY); printf(slave device: %s\n, device); master_file = fdopen(master_fd, r); slave_file = fdopen(slave_fd, w+); if (fork()) { fclose(slave_file); while (fgets(buf, sizeof(buf), master_file)) printf(parent got: %s, buf); } else { // child fclose(master_file); for (int i = 0; i 500; i++) { sleep(1); fprintf(slave_file, child's data (%d)\n, i); } } return 0; } = 21.11.09, 09:39, Till Harbaum / Lists li...@harbaum.org: Hi, thanks again for that hint. Unfortunately adding /* switch to line buffered mode */ if(setvbuf(fh, NULL, _IOLBF, 0)) perror(setvbuf(_IOLBF)); to the program posted by Dov doesn't change anything. Are there limitations on changing the buffer mode? E.g. only the transmitter side can do that? ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
On Thu, Nov 19, 2009 at 10:11 PM, Till Harbaum / Lists li...@harbaum.orgwrote: Hi, i am trying to run a text mode application in the background of my gtk one and display its output in a textview. I know this is supposed to be done using g_spawn_async_with_pipes and then link to the output via g_io_add_watch. I even got something that sort of works, but the output is very much delayed and comes in chunks and worse, the CPU load is at max while and after i run my code. Are there any examples for doing this? There must be many programs doing something similar to run e.g. some little helper program or similar. Can you consider using the VteTerminal[1] widget? This is the same terminal widget used in gnome-terminal and in Ubuntu/Debian graphical frontends to dpkg. It lets you embed a ternimal that you can bind to any program, you're not forced to bind it to a shell. VteTerminal will take care of monitoring your process and grabbing all output for you. The only drawback is that the widget doesn't work on win32. [1] http://library.gnome.org/devel/vte/unstable/VteTerminal.html Emmanuel Rodriguez ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
Here's my solution to the problem. It runs the external command in an external thread. This is probably an overkill for the problem at hand, on the other hand it is a good demo for how to create a worker thread and capture its output in the GUI. This currently does not work with windows at it is using popen() and g_io_channel_unix_new() but it should be trivial to fix and is left as an exercise for the reader. Compile with: gcc -o stdout-to-textview `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` stdout-to-textview.c //== // stdout-to-textview.c // // An example how to place stdout from a an external process // into a text view buffer by running the process in a separate // thread. // // This program is released under the LGPL v3.0. // // Dov Grobgeld dov.grobg...@gmail.com // Fri Nov 20 09:22:39 2009 //-- #include stdio.h #include stdlib.h #include gtk/gtk.h // This structure contains all the thread info for the job. typedef struct { GMutex *update_mutex; GCond *update_cond; GMutex *mutex_to_run; gchar *cmd; gchar *info; } JobData; // Sorry, out of laziness I made the widgets global. GtkWidget *w_text_view = NULL; GtkWidget *w_entry_cmd = NULL; GMutex *mutex_one_job_at_a_time = NULL; // Create the data for a job JobData *job_data_new(const char *cmd, GMutex *mutex_to_run) { JobData *job_data = g_new0(JobData, 1); job_data-cmd = g_strdup(cmd); job_data-update_mutex = g_mutex_new(); job_data-update_cond = g_cond_new(); job_data-mutex_to_run = mutex_to_run; return job_data; } // free the data from a job void job_data_free(JobData *job_data) { g_free(job_data-cmd); g_mutex_free(job_data-update_mutex); g_cond_free(job_data-update_cond); g_free(job_data); } // This function receives a requst from a worker thread asking to // update the gui with the required info. gboolean cb_update_job(JobData *job_data) { if (job_data-info) { GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w_text_view)); GtkTextIter end_iter; gtk_text_buffer_get_end_iter(text_buffer, end_iter); gtk_text_buffer_insert(text_buffer, end_iter, job_data-info, -1); gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(w_text_view), end_iter, 0.0, TRUE, 0.0, 0.5); g_free(job_data-info); job_data-info = NULL; } // Indicate that the update is done g_mutex_lock(job_data-update_mutex); g_cond_signal(job_data-update_cond); g_mutex_unlock(job_data-update_mutex); return FALSE; } // A helper function run in the job thread receiving the string that // should be displayed in the textview. void job_add_to_text_viewer(JobData *job_data, const char *info) { job_data-info = g_strdup(info); // Lock mutex to make sure that we will receive the condition signal g_mutex_lock(job_data-update_mutex); g_idle_add((GSourceFunc)cb_update_job, job_data); // Wait for cb_update_job to tell me that the update is done g_cond_wait(job_data-update_cond, job_data-update_mutex); g_mutex_unlock(job_data-update_mutex); } // The thread entry point. It will do the job, send the data to the // GUI and self destruct when it is done. static gpointer thread_worker(JobData *job_data) { FILE *fh = popen(job_data-cmd,r); printf(thread_worker running %s\n, job_data-cmd); GIOChannel *gh = g_io_channel_unix_new(fileno(fh)); GIOStatus status; GError *error = NULL; gsize length; gsize terminator_pos; gchar *str_return; while( (status = g_io_channel_read_line(gh, str_return, length, terminator_pos, error)) == G_IO_STATUS_NORMAL) { job_add_to_text_viewer(job_data, str_return); g_free(str_return); } g_io_channel_unref(gh); pclose(fh); job_add_to_text_viewer(job_data, Job done!); g_mutex_unlock(job_data-mutex_to_run); g_thread_exit(NULL); if (job_data) job_data_free(job_data); return NULL; } // Callback for the run button void cb_clicked_run(GtkWidget *widget, gpointer user_data) { const gchar *cmd = gtk_entry_get_text(GTK_ENTRY(w_entry_cmd)); GError *error = NULL; printf(Run %s\n, cmd); // create a thread that will run the external command // tbd... JobData *job_data = job_data_new(cmd, mutex_one_job_at_a_time); g_thread_create((GThreadFunc)thread_worker,
Re: Capture console app output into texview?
Hi, thanks a lot for those hints. The interesting part is that your program below shows the same behaviour: I don't see any output until the embedded application (geotoad in this case) has ended. This is rather annoying as the program runs quite some seconds and the user may think something is broken. Perhaps geotoad misses some flushs, but it does not show the problem when being run from the xterminal/whatever. Just for the context: I am working on gpxview (http://maemo.org/downloads/product/OS2008/gpxview/) a geocaching application written for hildon/maemo (but also runnable on plain gtk). And i want to embed geotoad (http://code.google.com/p/geotoad/) to gather/spider live geocaching info while on the go. Thanks again, Till Am Freitag 20 November 2009 schrieb Dov Grobgeld: Here's my solution to the problem. It runs the external command in an external thread. This is probably an overkill for the problem at hand, on the other hand it is a good demo for how to create a worker thread and capture its output in the GUI. This currently does not work with windows at it is using popen() and g_io_channel_unix_new() but it should be trivial to fix and is left as an exercise for the reader. Compile with: gcc -o stdout-to-textview `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` stdout-to-textview.c //== // stdout-to-textview.c // // An example how to place stdout from a an external process // into a text view buffer by running the process in a separate // thread. // // This program is released under the LGPL v3.0. // // Dov Grobgeld dov.grobg...@gmail.com // Fri Nov 20 09:22:39 2009 //-- #include stdio.h #include stdlib.h #include gtk/gtk.h // This structure contains all the thread info for the job. typedef struct { GMutex *update_mutex; GCond *update_cond; GMutex *mutex_to_run; gchar *cmd; gchar *info; } JobData; // Sorry, out of laziness I made the widgets global. GtkWidget *w_text_view = NULL; GtkWidget *w_entry_cmd = NULL; GMutex *mutex_one_job_at_a_time = NULL; // Create the data for a job JobData *job_data_new(const char *cmd, GMutex *mutex_to_run) { JobData *job_data = g_new0(JobData, 1); job_data-cmd = g_strdup(cmd); job_data-update_mutex = g_mutex_new(); job_data-update_cond = g_cond_new(); job_data-mutex_to_run = mutex_to_run; return job_data; } // free the data from a job void job_data_free(JobData *job_data) { g_free(job_data-cmd); g_mutex_free(job_data-update_mutex); g_cond_free(job_data-update_cond); g_free(job_data); } // This function receives a requst from a worker thread asking to // update the gui with the required info. gboolean cb_update_job(JobData *job_data) { if (job_data-info) { GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w_text_view)); GtkTextIter end_iter; gtk_text_buffer_get_end_iter(text_buffer, end_iter); gtk_text_buffer_insert(text_buffer, end_iter, job_data-info, -1); gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(w_text_view), end_iter, 0.0, TRUE, 0.0, 0.5); g_free(job_data-info); job_data-info = NULL; } // Indicate that the update is done g_mutex_lock(job_data-update_mutex); g_cond_signal(job_data-update_cond); g_mutex_unlock(job_data-update_mutex); return FALSE; } // A helper function run in the job thread receiving the string that // should be displayed in the textview. void job_add_to_text_viewer(JobData *job_data, const char *info) { job_data-info = g_strdup(info); // Lock mutex to make sure that we will receive the condition signal g_mutex_lock(job_data-update_mutex); g_idle_add((GSourceFunc)cb_update_job, job_data); // Wait for cb_update_job to tell me that the update is done g_cond_wait(job_data-update_cond, job_data-update_mutex); g_mutex_unlock(job_data-update_mutex); } // The thread entry point. It will do the job, send the data to the // GUI and self destruct when it is done. static gpointer thread_worker(JobData *job_data) { FILE *fh = popen(job_data-cmd,r); printf(thread_worker running %s\n, job_data-cmd); GIOChannel *gh = g_io_channel_unix_new(fileno(fh)); GIOStatus status; GError *error = NULL; gsize length; gsize terminator_pos; gchar *str_return; while( (status = g_io_channel_read_line(gh, str_return, length,
Re: Capture console app output into texview?
On Fri, Nov 20, 2009 at 03:09:56PM +0100, Till Harbaum / Lists wrote: The interesting part is that your program below shows the same behaviour: I don't see any output until the embedded application (geotoad in this case) has ended. This is rather annoying as the program runs quite some seconds and the user may think something is broken. Perhaps geotoad misses some flushs, but it does not show the problem when being run from the xterminal/whatever. Terminals are normaly line-buffered while pipes are block-buffered, see setvbuf(3) for some info. So the buffering behaviour differs depending on where the output goes. Yeti ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
RE: Capture console app output into texview?
-Original Message- From: gtk-app-devel-list-boun...@gnome.org [mailto:gtk-app-devel-list-boun...@gnome.org] On Behalf Of Till Harbaum / Lists Sent: Thursday, November 19, 2009 4:11 PM To: gtk-app-devel-list@gnome.org Subject: Capture console app output into texview? Hi, i am trying to run a text mode application in the background of my gtk one and display its output in a textview. I know this is supposed to be done using g_spawn_async_with_pipes and then link to the output via g_io_add_watch. I even got something that sort of works, but the output is very much delayed and comes in chunks and worse, the CPU load is at max while and after i run my code. Are there any examples for doing this? There must be many programs doing something similar to run e.g. some little helper program or similar. Regards, Till ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list Try using fork() and execlp(). ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: Capture console app output into texview?
On Thu, 19 Nov 2009 22:11:18 +0100 Till Harbaum / Lists li...@harbaum.org wrote: Hi, i am trying to run a text mode application in the background of my gtk one and display its output in a textview. I know this is supposed to be done using g_spawn_async_with_pipes and then link to the output via g_io_add_watch. I even got something that sort of works, but the output is very much delayed and comes in chunks and worse, the CPU load is at max while and after i run my code. Are there any examples for doing this? There must be many programs doing something similar to run e.g. some little helper program or similar. You generally won't get away with forking after the gtk+ main loop is running. You should fork before the main loop is running, and if you cannot do that start a new thread to fork from. If you do the latter on a POSIX (unix-like) system you must only call async-signal-safe functions between the fork and the exec*. If you are using windows, I do not know what the restraints are. Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list