suaveant has asked for the wisdom of the Perl Monks concerning the following question:

I am writing myself a cd ripper that uses bladeenc and cdparanoia, both of which write status output constantly to the page, which I would like to show, but am running them in parallel. Is it possible to use Curses or something similar to split the screen and have one display in the top half and one in the lower? I figure I can use open to fork the process and get a file handle to its output, but can I feed that to something useful? The newterm function in curses looks promising, but the docs are dismal and I can't locate any examples of its use...

They both use terminal manipulations of their own to print their statuses...

                - Ant
                - Some of my best work - (1 2 3)

Replies are listed 'Best First'.
Re: Splitting output
by dmmiller2k (Chaplain) on Jan 11, 2002 at 03:26 UTC

    It's been some years since I've worked with curses (nevermind ncurses), but you can probably throw together some sort of curses-based shell (in Perl, I'd imagine) which throws two windows up, sets up both of your processes writing into pipes, and alternates checking them/reading from them (using select from the socket API, I'd imagine to determine which to read from next).

    # Something like this: use IO::Select; my $bladeenc_cmd = 'bladeenc -whatever args'; my $cdparanoia_cmd = 'cdparanoia -whatever else args'; open P1, "$bladeenc_cmd|" or die "bladeenc: $!"; open P2, "$cdparanoia_cmd|" or die "cdparanoia: $!"; local $SIG{PIPE} = sub { warn "pipe closed"; } my $s = IO::Select->new(); my $timeout = 100; # msec(?) $s->add(\*P1); $s->add(\*P2); my @ready; while (@ready = $s->can_read($timeout)) { foreach my $fh (@ready) { if ($fh == \*P1) { my $line = <$fh>; # write to first window } if ($fh == \*P2) { my $line = <$fh>; # write to second window } } } # you get the idea ...

    Update: don't actually need Socket.pm. Added notation referring to bladeenc and cdparanoia command lines.

    dmm

    You can give a man a fish and feed him for a day ...
    Or, you can
    teach him to fish and feed him for a lifetime
      Just to add to dmm's code. If you don't really care about scrolling and buffering the output, you could use this for the write to window:
      #!/usr/local/bin/perl -w # Something like this: use IO::Select; use Curses; my $win = new Curses; my $x = $win->getmaxx; my $y = $win->getmaxy; my $m = int( $y/2 ); my $r = $x-2; my $div = "-"x$r; my $one_s = 1; my $one_e = $m-1; my $two_s = $m+1; my $two_e = $y-2; $win->box( '|', '-' ); $win->addstr( $m, 1, $div ); $win->refresh; my $bladeenc_cmd = 'bladeenc -whatever args'; my $cdparanoia_cmd = 'cdparanoia -whatever else args'; open P1, "$bladeenc_cmd|" or die "bladeenc: $!"; open P2, "$cdparanoia_cmd|" or die "cdparanoia: $!"; local $SIG{PIPE} = sub { warn "pipe closed"; }; my $s = IO::Select->new(); my $timeout = 100; # msec(?) $s->add(\*P1); $s->add(\*P2); my $one_cnt = $one_s; my $two_cnt = $two_s; my @ready; while (@ready = $s->can_read($timeout)) { foreach my $fh (@ready) { if ($fh == \*P1) { my $line = <$fh>; if( $line ) { $win->addstr( $one_cnt, 1, $line ); $one_cnt++; $one_cnt = $one_s if $one_cnt > $one_e; $win->refresh; } } if ($fh == \*P2) { my $line = <$fh>; if( $line ) { $win->addstr( $two_cnt, 1, $line ); $two_cnt++; $two_cnt = $two_s if $two_cnt > $two_e; $win->refresh; } } } }

      It's not pretty but it does work.

      derby