Thank you both. The option to tail definately handles the 'slow' part. Now I just need to handle the fragmented part. I think my problem is in the fact that everytime new data is in the filehandle, the buffer is overwritten. Is there a way to append data to the end of the buffer as it comes in? I'm sorry I didn't post the full program before, here it is (Excuse the sloppiness - it's been a learning experience):
#!/usr/bin/perl use strict; use warnings; use Gtk2 '-init'; use Glib qw/TRUE FALSE/; use FileHandle; use Gtk2::Helper; use Linux::CDROM; my $cddrive = "/dev/cdrom"; my $mountedcd = "/media/cdrom1"; our $cd = Linux::CDROM->new("$cddrive"); sub give_err { my ($fh, $msg) = @_; print $fh $msg; $cd->close; exit(1); } sub ripCD { my ($button, $passed) = @_; my $pid = fork(); if ($pid != 0) { return; } my $data = $passed->[0]; my $label =$passed->[1]; my $writefh = $passed->[2]; my $buffer = $passed->[3]; $cd->drive_status == 4 or give_err ($writefh, "No CD in drive! Insert CD and try + again. " . $cd->disc_status); my $case_number = $data->get_text; if ($case_number eq "") { $case_number = "temp"; } my $datestamp = `date +%Y%m%d%H%M%S `; my $id = ("$case_number.$datestamp"); chomp($id); system("echo 'Start of new job. ID=$id' >> /usr/rip/cdimport.log" +); system("echo '---------------------------------------------------- +---------------------------' >> /usr/rip/cdimport.log"); print $writefh "ID is $id"; system("mkdir /tmp/$id/"); chdir "/tmp/$id"; my $cdtype = $cd->disc_status; if ($cdtype==CDS_AUDIO) { print $writefh "Status: Ripping Audio CD..."; system("cdparanoia -B -e 2>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: CDParanoia Failed: $?"); print $writefh "Status: Converting to MP3..."; system("find /tmp/$id/ -iname \"*.wav\" -print0 | xargs -0 -n +1 -I '{}' ffmpeg -i '{}' -f mp3 '{}'.mp3 2>> /usr/rip/cdimport.log") +== 0 or give_err ($writefh, "ERROR: Failed to convert WAV to M +P3: $?"); system("find /tmp/$id/ -iname \"*.mp3\" -print0 | xargs -0 -n +10 rename 's/\.cdda\.wav\.mp3/\.mp3/i' 1>> /usr/rip/cdimport.log") == + 0 or give_err ($writefh, "ERROR: Failed to rename files: $? +"); system("find /tmp/$id/ -iname \"*.mp3\" -print0 | xargs -0 -n +10 rename 's/track/$id-/i' 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to rename files: $? +"); system("find /tmp/$id/ -iname \"*.wav\" -print0 | xargs -0 -n +10 rm -rf 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to delete WAV Files +: $?"); } else { print $writefh "Status: Mounting CD-ROM..."; system("umount $cddrive 1>> /usr/rip/cdimport.log"); system("mount $cddrive 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to mount CD-Rom: $?" +); print $writefh "Copying CD..."; system("mkdir -v /tmp/$id/ 1>> /usr/rip/cdimport.log"); system("cp $mountedcd/* -vR /tmp/$id/ 1>> /usr/rip/cdimport.lo +g") == 0 or give_err ($writefh, "ERROR: Failed to copy files: $?") +; system("chmod -v +w /tmp/$id -R 1>> /usr/rip/cdimport.log") == + 0 or give_err ($writefh, "ERROR: Failed to give write permi +ssion: $?"); print $writefh "Converting any WAV files to MP3..."; if (system("find /tmp/$id/ -iname \"*.wav\" -print0 | xargs -0 + -n 1 -I '{}' ffmpeg -i '{}' -f mp3 '{}'.mp3 1>> /usr/rip/cdimport.lo +g") == 0) { system("find /tmp/$id/ -iname \"*.mp3\" -print0 | xarg +s -0 -n 10 rename -v 's/\.wav\.mp3/\.mp3/i' 1>> /usr/rip/cdimport.log +") == 0 or give_err ($writefh, "ERROR: Failed to rename f +iles: $?"); system("find /tmp/$id/ -iname \"*.wav\" -print0 | xarg +s -0 -n 10 rm -vrf 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to delete W +AV Files: $?"); } else { print $writefh "Failed to convert WAV to MP3 - Skippi +ng"; } system("umount -v $cddrive 1>> /usr/rip/cdimport.log"); } my ($start, $end) = $buffer->get_bounds; open INPUT, "> /tmp/$id/notes.txt"; print INPUT $buffer->get_text($start, $end, TRUE); close INPUT; print $writefh "Creating Archive..."; chdir("/tmp/"); system("tar --verbose --create --bzip2 --file=/usr/rip/pending/$id +.bz2 $id/ 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to compress files: $?") +; print $writefh "Cleaning up old files..."; system("rm -rfv /tmp/$id/ 1>> /usr/rip/cdimport.log") == 0 or give_err ($writefh, "ERROR: Failed to delete old files: $? +"); $cd->eject; $cd->close; print $writefh "Ready for next CD"; exit(0); } sub watch_console { my ($fd, $fh, $buffer) = @_; my $sysbuffer; if ( not sysread($fh, $sysbuffer, 4096) ) { # obviously the connected pipe was closed Gtk2::Helper->remove_watch ($fd) or die "couldn't remove watcher"; close($fh); return 1; } #$buffer->set_text($sysbuffer); $buffer->set_text($sysbuffer); #always return TRUE to continue the callback return 1; } sub updateStatus { my ($fh, $tag, $label) = @_; my $buffer; if ( not sysread($fh, $buffer, 4096) ) { # obviously the connected pipe was closed Gtk2::Helper->remove_watch ($tag) or die "couldn't remove watcher"; # close($fh); return 1; } $label->set_text("$buffer"); return 1; } sub delete_event { Gtk2->main_quit; return FALSE; } # See if this was called with audio or data my $cdtype = $ARGV[0]; my ($readfh, $writefh) = FileHandle::pipe; my $fh = FileHandle->new(); #open ($fh, "/usr/rip/cdimport.log"); open ($fh, "tail -f -s .1 /usr/rip/cdimport.log |"); # Create widgets # Set up main window my $window = Gtk2::Window->new('toplevel'); $window->set_title("Metropolitan Interpreters and Translators"); $window->signal_connect(delete_event => \&delete_event); $window->set_border_width(10); $window->set_size_request( 800, 400); my $box1 = Gtk2::VBox->new(FALSE,0); $window->add($box1); # Create status bar my $label = Gtk2::Label->new("Status: Not running."); $label->set_alignment(0.0, 0.0); $box1->pack_end($label, TRUE, FALSE, 0); # Create Case Number text box my $frame = Gtk2::Frame->new('Enter in the Case Number for this CD'); my $entry = Gtk2::Entry->new; $frame->add($entry); $frame->set_border_width(0); $box1->pack_start($frame, TRUE, TRUE, 0); # Create textview box for notes $frame = Gtk2::Frame->new('Enter in any relevant notes'); my $textBox = Gtk2::TextView->new; my $scroll = Gtk2::ScrolledWindow->new; my $event_box = Gtk2::EventBox->new; my $color = Gtk2::Gdk::Color->parse ("black"); $event_box->modify_bg ('normal', $color); my $align = Gtk2::Alignment->new (0.5, 0.5, 1.0, 1.0); $align->set_border_width (1); $scroll->add($event_box); $event_box->add ($align); $align->add ($textBox); my $buffer = $textBox->get_buffer; my $end_mark = $buffer->create_mark( 'end', $buffer->get_end_iter, FAL +SE ); $buffer->signal_connect( insert_text => sub { $textBox->scroll_to_mark( $end_mark, 0.0, TRUE, 0.0, 0.0 ); } ); $frame->add($scroll); $box1->pack_start($frame, TRUE, TRUE, 0); $textBox->set_buffer($buffer); # Create console text box $frame = Gtk2::Frame->new('Console Window'); my $ctextBox = Gtk2::TextView->new; my $cscroll = Gtk2::ScrolledWindow->new; my $cevent_box = Gtk2::EventBox->new; $color = Gtk2::Gdk::Color->parse ("black"); $cevent_box->modify_bg ('normal', $color); my $calign = Gtk2::Alignment->new (0.5, 0.5, 1.0, 1.0); $calign->set_border_width (1); $cevent_box->add ($calign); $calign->add ($ctextBox); $cscroll->add($cevent_box); my $cbuffer = $ctextBox->get_buffer; my $cend_mark = $cbuffer->create_mark( 'end', $cbuffer->get_end_iter, +FALSE ); $cbuffer->signal_connect( insert_text => sub { $ctextBox->scroll_to_mark( $cend_mark, 0.0, TRUE, 0.0, 0.0 ); } ); $frame->add($cscroll); $box1->pack_end($frame, TRUE, TRUE, 0); $ctextBox->set_buffer($cbuffer); $ctextBox->set_editable(FALSE); $cbuffer->set_text("Console window"); # Create buttons my $box2 = Gtk2::HBox->new(FALSE, 0); my $button = Gtk2::Button->new(" Start "); $button->signal_connect(clicked => \&ripCD, [$entry, $label, $writefh, + $buffer, $cdtype]); $box2->pack_start($button, TRUE, FALSE, 10); $button = Gtk2::Button->new(" Cancel "); $button->signal_connect(clicked => \&delete_event); $box2->pack_start($button,TRUE, FALSE, 0); $box1->pack_start($box2, TRUE, FALSE, 0); my $tag; $tag = Gtk2::Helper->add_watch ( $readfh->fileno, 'in', sub { updateStatus ($readfh, $tag, $label); }); my $ctag; $ctag = Gtk2::Helper->add_watch ( $fh->fileno, 'in', sub { watch_console ($ctag, $fh, $cbuffer); }); $window->show_all(); Gtk2->main; system("killall tail");

In reply to Re: Realtime update of a textbuffer from STDOUT/STDERR in Gtk2 by fang0654
in thread Realtime update of a textbuffer from STDOUT/STDERR in Gtk2 by fang0654

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.