Yeah, buffering can be a sticky issue.  At a minimum, the sender needs to turn 
it off.  In your test_output.pl, you should do something like this on the file 
handle to which you’re writing,

   use IO::Handle;
   $fh->autoflush(TRUE);

which you might see done this way,

   $fhPrev=select($fh);
   $|=TRUE;
   select($fhPrev);

or with an older idiom for maximum compactness/obfuscation,

   select((select($fh),$|=TRUE)[0]);

or with an I/O layer.

   binmode($fh,”:unix”) or die “Unable to binmode: $!.\n”;

Good luck.

Jim

From: Williams, James P2 (US)
Sent: Friday, December 11, 2015 11:38 AM
To: 'orangensa...@web.de' <orangensa...@web.de>; 'gtk-perl-list@gnome.org' 
<gtk-perl-list@gnome.org>
Subject: RE: EXTERNAL: stdout/sterr to GtkTextView at runtime

One way to deal with this is to open a pipe to the program instead of using 
backticks.

   use Glib qw(TRUE FALSE);
   use IO::File;

   ...

   my($cmd)=”/usr/bin/perl test_output.pl”;
   my($fh)=new IO::File(“$cmd 2>&1 |”);
   die “$0: Unable to open pipe from $cmd: $!.\n” if !$fh;

Then, add a function to be called when input is available on that file handle.

   my($io)=Glib::IO->add_watch($fh->fileno(),[qw(in hup)],sub 
{ioCB($fh,$cmd,@_)});

where the callback would read the file handle, and append what it gets to your 
widget.

   sub ioCB
   {
      my($fh,$cmd,$fd,$cond)=@_;
      my(@lines,$done);


      if ($cond & ‘hup’) {
         @lines=$fh->getlines();
         $done=TRUE;
      } elsif ($cond & ‘in’) {
         @lines=($fh->getline());  #read only one line; may block if we try more
      }

      if (@lines) {
         ...
         $buf->insert($buf->get_end_iter(),join ‘’,@lines);
         ...
      }

      if ($done && !$fh->close()) {
         showError($!
            ? “Unable to close pipe to $cmd: $!.”
            : “Got non-zero exit status from $cmd, $?.”);
      }

      return !$done;                       #i.e., keep IO channel if not at EOF
   }

$io in the earlier code can be used to remove the callback later, or you can 
just return FALSE from the callback, as I do above.  You can get more details 
in the Glib::MainLoop docs and those for the C bindings that module wraps.

Another way to deal with this is to do blocking reads in a separate thread, but 
if your Perl skills are weak, I’d go with this simpler IO channel approach.

Good luck.

Jim

From: gtk-perl-list [mailto:gtk-perl-list-boun...@gnome.org] On Behalf Of 
orangensa...@web.de<mailto:orangensa...@web.de>
Sent: Thursday, December 10, 2015 11:14 PM
To: gtk-perl-list@gnome.org<mailto:gtk-perl-list@gnome.org>
Subject: EXTERNAL: stdout/sterr to GtkTextView at runtime

Hi,

I'm writing a gui for an existing program that can run for a while. I want to 
display all possible terminal output of this program in a GtkTextView. So far i 
failed to display the output at runtime. I tried this

my $iter = $textbuffer->get_end_iter;
my $command = `perl test_output.pl 2>&1`;
$textbuffer->insert($iter, $command);

which isn't working the way i want. My program is blocked while test_output.pl 
is running. I tried to use

my $command = system("perl test_output.pl 2>&1 &");

instead but while my program keeps running, all output is shown in the terminal 
again.


How can i achieve to get all output at runtime in my textview? And how do i 
check if test_output is done running? I found an old solution using Gtk+ itself 
but my perl skills aren't good enough to reproduce this:
https://mail.gnome.org/archives/gtk-list/2006-February/msg00040.html


I'm using Gtk3.


Thanks for any help.
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtk-perl-list

Reply via email to