problem with Gtk2::Helper & STDOUT

View: New views
4 Messages — Rating Filter:   Alert me  

problem with Gtk2::Helper & STDOUT

by Landry Breuil-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

i'm asking here after turning around a strange problem for days...
i can't get to make Gtk2::Helper watch the STDOUT of the current program
(not from a forked child or whatever). The idea is to do smth like 'tail' but
in a Gtk Widget or VTE Widget, but showing current process STDOUT.

I think i tried everything so far, all supposed (from my understanding
of the docs) to catch the 'FOO'
printed on STDOUT :

Glib::IO->add_watch (fileno (STDOUT), 'in', sub {
        my $fd = shift;
        print STDERR "received \"$_\"\n" while (<$fd>);
        return TRUE;
});
print "FOO\n";

same thing with an anonymous file handler :

open my $fh, "+>", undef or die "blaaah : $!";
select $fh;
my $id = Glib::IO->add_watch (fileno $fh, 'in', sub {
        my $fd = shift;
        print STDERR "received \"$_\"\n" while (<$fd>);
        return TRUE;
});
print "FOO\n";

With those examples, 'FOO' is dropped.

Is there a way to realize this ? I'd really appreciate some help,
because this is turning me mad since days. Apparently, bare glib allows
io channels to be created with stdout.. maybe the problem lies in the
fact that i want to _read_ on  STDOUT. I also tried :

pipe ($read,$fh);
select $fh;
Gtk2::Helper->add_watch (fileno($read), 'in', sub {cbk($fh)});

With no luck.

Thanks for any pointers/insights.

Landry

Ps: here's the whole test program :

#!/usr/bin/perl -w

use strict;
use Glib 1.040, qw(TRUE FALSE);
use Gtk2;
use Data::Dumper;
use Gtk2::Helper;

Gtk2->init();

my $window = Gtk2::Window->new;
$window->signal_connect (delete_event => sub {exit});
$window->set_default_size (400, 300);
my $vbox = Gtk2::VBox->new;
$window->add ($vbox);
my $scroller = Gtk2::ScrolledWindow->new;
$vbox->add ($scroller);
my $textview = Gtk2::TextView->new;
my $buffer = $textview->get_buffer;
$buffer->create_mark ('end', $buffer->get_end_iter, FALSE);
$buffer->signal_connect (insert_text => sub { $textview->scroll_to_mark ($buffer->get_mark ('end'), 0.0, TRUE, 0, 0.5);});
$scroller->add ($textview);
my $button = Gtk2::Button->new ('go');
$button->signal_connect (clicked => \&button_handler);
$vbox->pack_start ($button, FALSE, FALSE, 0);
$window->show_all;
Gtk2->main;
exit;

sub button_handler {
        $button->set_sensitive (FALSE);
        my $fh;
        open ($fh, "+>", undef) or die "PROTCH:$!";
        select $fh;
        $|=1;
        Gtk2::Helper->add_watch (fileno($fh), 'in', sub {cbk($fh)});
        print STDERR "FOO1\n";
        print "FOO2\n";
        sleep 1;
        print $fh "FOO3\n";
        $buffer->insert ($buffer->get_end_iter, "done");
        $button->set_sensitive (TRUE);
};
sub cbk {
        my $fd = shift;
        my $buf;
        print STDERR Dumper($fd).fileno($fd)."!\n";
        while (sysread ($fd,$buf,1028)) {
                print STDERR "received \"$buf\"\n";
                $buffer->insert ($buffer->get_end_iter, $buf);
        }
}
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@...
http://mail.gnome.org/mailman/listinfo/gtk-perl-list

Re: problem with Gtk2::Helper & STDOUT

by Matthew Braid-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I don't think this is a Gtk issue - isn't STDOUT essentially a
write-only file handle?

Even if it's not, think of where the current position is. It will
start at eof, and when you write out to it it will stay at eof (after
anything you just wrote). So unless you seek backwards (which I don't
think you can do on STDOUT) there's never anything after the current
position, so there's never anything to read, so the watch never gets
triggered.

If you mapped STDOUT to a seekable read/write filehandle and made sure
you seek'd backwards every time you wrote to it, that _might_ trigger
a watch on that file handle (and you'd have to make sure you truncate
it in the watch or you'd end up repeating everything over and over
again). That sounds incredibly flaky though.

MB



2009/9/10 Landry Breuil <landry@...>:

> Hi,
>
> i'm asking here after turning around a strange problem for days...
> i can't get to make Gtk2::Helper watch the STDOUT of the current program
> (not from a forked child or whatever). The idea is to do smth like 'tail' but
> in a Gtk Widget or VTE Widget, but showing current process STDOUT.
>
> I think i tried everything so far, all supposed (from my understanding
> of the docs) to catch the 'FOO'
> printed on STDOUT :
>
> Glib::IO->add_watch (fileno (STDOUT), 'in', sub {
>        my $fd = shift;
>        print STDERR "received \"$_\"\n" while (<$fd>);
>        return TRUE;
> });
> print "FOO\n";
>
> same thing with an anonymous file handler :
>
> open my $fh, "+>", undef or die "blaaah : $!";
> select $fh;
> my $id = Glib::IO->add_watch (fileno $fh, 'in', sub {
>        my $fd = shift;
>        print STDERR "received \"$_\"\n" while (<$fd>);
>        return TRUE;
> });
> print "FOO\n";
>
> With those examples, 'FOO' is dropped.
>
> Is there a way to realize this ? I'd really appreciate some help,
> because this is turning me mad since days. Apparently, bare glib allows
> io channels to be created with stdout.. maybe the problem lies in the
> fact that i want to _read_ on  STDOUT. I also tried :
>
> pipe ($read,$fh);
> select $fh;
> Gtk2::Helper->add_watch (fileno($read), 'in', sub {cbk($fh)});
>
> With no luck.
>
> Thanks for any pointers/insights.
>
> Landry
>
> Ps: here's the whole test program :
>
> #!/usr/bin/perl -w
>
> use strict;
> use Glib 1.040, qw(TRUE FALSE);
> use Gtk2;
> use Data::Dumper;
> use Gtk2::Helper;
>
> Gtk2->init();
>
> my $window = Gtk2::Window->new;
> $window->signal_connect (delete_event => sub {exit});
> $window->set_default_size (400, 300);
> my $vbox = Gtk2::VBox->new;
> $window->add ($vbox);
> my $scroller = Gtk2::ScrolledWindow->new;
> $vbox->add ($scroller);
> my $textview = Gtk2::TextView->new;
> my $buffer = $textview->get_buffer;
> $buffer->create_mark ('end', $buffer->get_end_iter, FALSE);
> $buffer->signal_connect (insert_text => sub { $textview->scroll_to_mark ($buffer->get_mark ('end'), 0.0, TRUE, 0, 0.5);});
> $scroller->add ($textview);
> my $button = Gtk2::Button->new ('go');
> $button->signal_connect (clicked => \&button_handler);
> $vbox->pack_start ($button, FALSE, FALSE, 0);
> $window->show_all;
> Gtk2->main;
> exit;
>
> sub button_handler {
>        $button->set_sensitive (FALSE);
>        my $fh;
>        open ($fh, "+>", undef) or die "PROTCH:$!";
>        select $fh;
>        $|=1;
>        Gtk2::Helper->add_watch (fileno($fh), 'in', sub {cbk($fh)});
>        print STDERR "FOO1\n";
>        print "FOO2\n";
>        sleep 1;
>        print $fh "FOO3\n";
>        $buffer->insert ($buffer->get_end_iter, "done");
>        $button->set_sensitive (TRUE);
> };
> sub cbk {
>        my $fd = shift;
>        my $buf;
>        print STDERR Dumper($fd).fileno($fd)."!\n";
>        while (sysread ($fd,$buf,1028)) {
>                print STDERR "received \"$buf\"\n";
>                $buffer->insert ($buffer->get_end_iter, $buf);
>        }
> }
> _______________________________________________
> gtk-perl-list mailing list
> gtk-perl-list@...
> http://mail.gnome.org/mailman/listinfo/gtk-perl-list
>
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@...
http://mail.gnome.org/mailman/listinfo/gtk-perl-list

Re: problem with Gtk2::Helper & STDOUT

by muppet-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Sep 10, 2009, at 7:16 AM, Landry Breuil wrote:

> i'm asking here after turning around a strange problem for days...
> i can't get to make Gtk2::Helper watch the STDOUT of the current  
> program
> (not from a forked child or whatever). The idea is to do smth like  
> 'tail' but
> in a Gtk Widget or VTE Widget, but showing current process STDOUT.

As Matthew already mentioned, i don't think this is really a gtk+  
issue, but the fact that STDOUT is a write-only file handle always  
pointing at the end.

You may get more mileage out of a minor modification of your program,  
making evil use of some very perlish things:


> #!/usr/bin/perl -w
>
> use strict;
> use Glib 1.040, qw(TRUE FALSE);
> use Gtk2;
> use Data::Dumper;
> use Gtk2::Helper;
>
> Gtk2->init();
>
> my $window = Gtk2::Window->new;
> $window->signal_connect (delete_event => sub {exit});
> $window->set_default_size (400, 300);
> my $vbox = Gtk2::VBox->new;
> $window->add ($vbox);
> my $scroller = Gtk2::ScrolledWindow->new;
> $vbox->add ($scroller);
> my $textview = Gtk2::TextView->new;
> my $buffer = $textview->get_buffer;
> $buffer->create_mark ('end', $buffer->get_end_iter, FALSE);
> $buffer->signal_connect (insert_text => sub { $textview-
> >scroll_to_mark ($buffer->get_mark ('end'), 0.0, TRUE, 0, 0.5);});
> $scroller->add ($textview);
> my $button = Gtk2::Button->new ('go');
> $button->signal_connect (clicked => \&button_handler);
> $vbox->pack_start ($button, FALSE, FALSE, 0);
> $window->show_all;
> Gtk2->main;
> exit;
>
> sub button_handler {
> $button->set_sensitive (FALSE);

         # create a new tied handle with a callback that will
         # copy what ever we print to the window.
         tie *STDOUTANDWINDOW, 'LineCopy', *STDOUT, sub {
                         $buffer->insert ($buffer->get_end_iter, $_[0])
                 });
         select STDOUTANDWINDOW;

> print STDERR "FOO1\n";
> print "FOO2\n";

         # sleep 1 is evil, use a timeout, instead.
         Glib::Timeout->add (1000, sub { Gtk2->main_quit; FALSE });
         Gtk2->main;

> print STDOUTANDWINDOW "FOO3\n";
> $buffer->insert ($buffer->get_end_iter, "done");
> $button->set_sensitive (TRUE);

         # undo what we did.
         untie *STDOUTANDWINDOW;
         select STDOUT;
> };



package LineCopy;

sub TIEHANDLE {
        my ($class, $handle, $callback) = @_;
        return bless { buffer => '', handle => $handle, callback =>  
$callback };
}

sub PRINT {
        my $self = shift;
        foreach (@_) {
               $self->{callback} ($_) if $self->{callback};
               print { $self->{handle} } $_;
        }
}



--
The trees on the bus go "pyoo pyoo pyoo..."
   -- Yvonne, singing, um, something

_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@...
http://mail.gnome.org/mailman/listinfo/gtk-perl-list

Re: problem with Gtk2::Helper & STDOUT

by Kevin Ryde :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Landry Breuil <landry@...> writes:
>
> current process STDOUT.

I don't think add_watch is geared to that.  Something like IO::Capture
that gets under the perl file handle might be what you want.  Except
IO::Capture and others seem geared towards holding the output rather
than making a callback immediately.  Your own tie() of STDOUT might be
the way, maybe a bit tricky.

Matthew Braid <ptkperl@...> writes:
>
> If you mapped STDOUT to a seekable read/write filehandle

Maybe a pipe with STDOUT on the write end, and add_watch on the read
end.  It'd have the advantage of getting any direct C code writes too.
Except I suppose it'd be deadlocked if writing more than PIPE_BUF before
the main loop gets a chance to read it back.
_______________________________________________
gtk-perl-list mailing list
gtk-perl-list@...
http://mail.gnome.org/mailman/listinfo/gtk-perl-list