Re: Capture console app output into texview?

2009-11-23 Thread Till Harbaum / Lists
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?

2009-11-21 Thread Till Harbaum / Lists
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?

2009-11-21 Thread David Nečas
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?

2009-11-21 Thread 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?

2009-11-20 Thread Emmanuel Rodriguez
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?

2009-11-20 Thread 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,
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?

2009-11-20 Thread Till Harbaum / Lists
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?

2009-11-20 Thread David Nečas
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?

2009-11-19 Thread Boggess Rod
 

 -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?

2009-11-19 Thread Chris Vine
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