Here is an IRC client written in Gtk2 and I would like to tweak it a bit so I'm looking for a little insight. There seems to be a little problem with the scrolling. when a user types a message that is longer than the window and at the bottom of the window instead of scrolling to the last lines of the message it just scrolls to the first line. It is rather annoying and I would like to fix it but I'm not sure how? Currently the scrolling is:
$chat_buffer->signal_connect(insert_text => sub { $chat_textview->scroll_to_mark( $chat_buffer->get_mark('end'), + 0.0, TRUE, 0, 0.5 ); });

Another addition I would like to add is sound. Playing a wav whenever there is a new message would be a great addition. I tried using Audio::Play to get it to work but no sound was produces so any ideas would help.

#!/usr/local/bin/perl -w use strict; use Gtk2 '-init'; use Glib qw/TRUE FALSE/; use Net::IRC; use threads; use threads::shared; my $irc = new Net::IRC; my $chat_state = 'Connect'; my $chat_entry; my $chat_send_sig; my $chat_textview; my $chat_button; my $sys_msg; my $tag; my $job = 1; my $die:shared = 0; my $chat_start:shared = 0; my $channel:shared = "#GRRUVI"; my $irc_server:shared = "irc.servercentral.net"; my $nick:shared = "VCBase"; my $msg:shared; my $post:shared = 0; my $name:shared = 0; my $list:shared; ################################################# #Threads my $thread_chat = threads->new(\&chat); ################################################# ################################################# #Timeout my $timer_post = Glib::Timeout->add(100, \&post); ################################################# #-------------------Main Loop------------------- &chat_build; Gtk2->main; ####################CHAT BLOCK#################### #-------------------chat Build------------------- sub chat_build { my $chat_window = Gtk2::Window->new('toplevel'); $chat_window->set_title('Chat Client'); $chat_window->set_position('center'); $chat_window->set_default_size( 300, 300 ); $chat_window->signal_connect(delete_event=> sub{ $die = 1; $thread_chat->join; Gtk2->main_quit; }); $chat_entry = Gtk2::Entry->new; my $chat_vbox = Gtk2::VBox->new; my $chat_scroll = Gtk2::ScrolledWindow->new; $chat_scroll->set_shadow_type( 'etched-out'); $chat_textview = Gtk2::TextView->new; my $chat_buffer = $chat_textview->get_buffer; $chat_buffer->create_mark( 'end', $chat_buffer->get_end_iter, FALS +E ); $chat_buffer->signal_connect(insert_text => sub { $chat_textview->scroll_to_mark( $chat_buffer->get_mark('end'), + 0.0, TRUE, 0, 0.5 ); }); $chat_button = Gtk2::Button->new; $chat_button->set_label($chat_state); # allows for sending each line with an enter keypress $chat_send_sig = $chat_entry->signal_connect ('key-press-event' => + sub { my ($widget,$event)= @_; if( $event->keyval() == 65293){ # a return key press $msg = $chat_entry->get_text; $chat_entry->set_text(''); $chat_entry->set_position(0); $chat_start = 2; $name = $nick; $post = 6; #print "$chat_start\n"; } }); $chat_entry->signal_handler_block($chat_send_sig); #not connected +yet $chat_entry->set_editable(0); $chat_textview->set_editable(0); $chat_textview->set_cursor_visible(0); $chat_textview->set_wrap_mode('word'); $chat_scroll->add($chat_textview); $chat_vbox->add($chat_scroll); $chat_vbox->pack_start( $chat_entry, FALSE, FALSE, 0 ); $chat_vbox->pack_start( $chat_button, FALSE, FALSE, 0 ); $chat_window->add($chat_vbox); $chat_window->show_all; $chat_button->signal_connect("clicked" => sub { if ($chat_state eq 'Connect') { $chat_button->set_label('Disconnect'); $chat_state='Disconnect'; $chat_start = 1; $post = 1; } else { $chat_button->set_label('Connect'); $chat_state='Connect'; $chat_start = 0; $post = 5; } }); return 1; } #-------------------Post to Textview------------------- sub post { #my ($name, $msg) = @_; my @time = gmtime; my $hour = $time[2]; my $min = $time[1]; my $sec = $time[0]; $hour = "0$time[2]" if $time[2] < 10; $min = "0$time[1]" if $time[1] < 10; $sec = "0$time[0]" if $time[0] < 10; my $post_time = "($hour:$min:$sec)"; my $chat_buffer = $chat_textview->get_buffer; #connecting if ($post == 1){ $chat_buffer->insert( $chat_buffer->get_end_iter, "Connecting +to $irc_server..\n" ); $post = 0; print CHAT "Connecting to $irc_server..\n" if $job == 3; } #Connected if ($post == 2){ $chat_buffer->insert( $chat_buffer->get_end_iter, "Connected t +o $irc_server\n" ); $chat_entry->set_editable(1); $chat_entry->grab_focus; $chat_entry->signal_handler_unblock ($chat_send_sig); $post = 0; print CHAT "Connected to $irc_server\n" if $job == 3; } #Joined if ($post == 3){ if ($name ne $nick){ $chat_buffer->insert_with_tags( $chat_buffer->get_end_iter +, "$name Joined $channel$post_time\n", $chat_buffer->create_tag($tag, + foreground=>'red')); } else{ $chat_buffer->insert( $chat_buffer->get_end_iter, "$name J +oined $channel$post_time\n"); } $post = 0; print CHAT "$name Joined $channel$post_time\n" if $job == 3; } #Users if ($post == 4){ #print "$list\n"; $chat_buffer->insert( $chat_buffer->get_end_iter, "Users on $c +hannel: $list\n" ); $post = 0; print CHAT "Users on $channel: $list\n" if $job == 3; } #disconnect if ($post == 5){ $chat_buffer->insert( $chat_buffer->get_end_iter, "Disconnecti +ng$post_time\n" ); $chat_entry->set_editable(0); $chat_entry->grab_focus; $chat_entry->signal_handler_block ($chat_send_sig); $post = 0; print CHAT "Disconnecting$post_time\n" if $job == 3; } #Posts if ($post == 6){ if ($name ne $nick){ $chat_buffer->insert_with_tags( $chat_buffer->get_end_iter +, "$name$post_time: $msg\n", $chat_buffer->create_tag($tag, foregroun +d=>'red')); } else{ $chat_buffer->insert( $chat_buffer->get_end_iter, "$name$p +ost_time: $msg\n"); } print CHAT "$name$post_time: $msg\n" if $job == 3; $post = 0; } #Disconnected if ($post == 7){ $chat_buffer->insert( $chat_buffer->get_end_iter, "Disconnecte +d->Reconnecting$post_time\n"); print CHAT "Disconnected->Reconnecting$post_time\n" if $job == + 3; $post = 0; } #Nick taken if ($post == 8){ $chat_buffer->insert( $chat_buffer->get_end_iter, "Nick is Tak +en->Please Change\n"); $chat_entry->set_editable(0); $chat_entry->grab_focus; $chat_entry->signal_handler_block ($chat_send_sig); $chat_start = 0; $chat_state = 'Connect'; $chat_button->set_label($chat_state); $chat_buffer->insert( $chat_buffer->get_end_iter, "Nick is Tak +en->Please Change\n" ); print CHAT "Connecting to $irc_server..\n" if $job == 3; $post = 0; } #Quit if ($post == 9){ $chat_buffer->insert_with_tags( $chat_buffer->get_end_iter, "$ +name has QUIT$post_time\n", $chat_buffer->create_tag($tag, foreground +=>'red')); print CHAT "$name has QUIT$post_time\n" if $job == 3; $post = 0; } return 1; } ################################################## ####################Threads#################### sub chat{ while (1){ my $conn; goto END if $die == 1; if ($chat_start == 1){ print "starting...\n"; $conn = $irc->newconn(Server => $irc_server, Port => 6667, Nick => $nick, Ircname => "CoCoNUE Member $nick") or die "Can't connect to IRC server\n"; #Install Handlers $conn->add_handler('cping', \&on_ping); + # $conn->add_handler('crping', \&on_ping_reply); + # $conn->add_handler('join', \&on_join); + #3 $conn->add_handler('quit', \&on_quit); + #9 $conn->add_handler('public', \&on_public); + #6 $conn->add_global_handler([ 251,252,253,254,302,255 ], \&o +n_init); $conn->add_global_handler('disconnect', \&on_disconnect); + #7 $conn->add_global_handler(376, \&on_connect); + #2 $conn->add_global_handler(433, \&on_nick_taken); + #8 $conn->add_global_handler(353, \&on_names); + #4 for (;;){ $irc->do_one_loop; #print "Looped: Reading\n"; if ($chat_start == 2){ #print "Looped: Sending\n"; $conn->privmsg("$channel", "$msg"); $chat_start = 1 if $chat_start != 0; } goto END if $die == 1; last if $chat_start == 0; } $irc->removeconn($conn); } } END: } #-------------------Handlers------------------- # What to do when the bot successfully connects. sub on_connect { my $self = shift; $post = 2; sleep 1; print "Joining $channel...\n"; $self->join("$channel"); } # Handles some messages you get when you connect:::For testing sub on_init { my ($self, $event) = @_; my (@args) = ($event->args); shift (@args); print "*** @args\n"; } # What to do when someone leaves a channel the bot is on. sub on_quit { my ($self, $event) = @_; #my ($channel) = ($event->to)[0]; $name = $event->nick; $post = 9; printf "*** %s has left channel %s\n", $event->nick, $channel; } # What to do when someone joins a channel the bot is on. sub on_join { my ($self, $event) = @_; #my ($channel) = ($event->to)[0]; $name = $event->nick; $post = 3; sleep 1; printf "*** %s (%s) has joined channel %s\n", $event->nick, $event->userhost, $channel; if ($event->userhost =~ /^corbeau\@.*execpc\.com/) { # Auto-ops a +nyone who $self->mode("#IRC.pm", "+o", $event->nick); # matches hostmas +k. } } # Prints the names of people in a channel when we enter. sub on_names { my ($self, $event) = @_; my (@list) = ($event->args); # eat yer heart out, mjd! # splice() only works on real arrays. Sigh. ($channel, @list) = splice @list, 2; $list = join(" ", @list); print "$list\n"; $post = 4; print "Users on $channel: @list\n"; } # Yells about incoming CTCP PINGs. sub on_ping { my ($self, $event) = @_; my $name = $event->nick; $self->ctcp_reply($name, join (' ', ($event->args))); print "*** CTCP PING request from $name received\n"; } # Gives lag results for outgoing PINGs. sub on_ping_reply { my ($self, $event) = @_; my ($args) = ($event->args)[1]; my ($name) = $event->nick; $args = time - $args; print "*** CTCP PING reply from $name: $args sec.\n"; } # Change our nick if someone stole it. sub on_nick_taken { my ($self) = shift; #$chat_start = 0; #$chat_state = 'Connect'; $post = 8; #$self->nick(substr($self->nick, -1) . substr($self->nick, 0, 8)); } # Reconnect to the server when we die. sub on_disconnect { my ($self, $event) = @_; $post = 7; print "Disconnected from ", $event->from(), " (", ($event->args())[0], "). Attempting to reconnect...\n"; $self->connect(); } # What to do when we receive channel text. sub on_public { my ($self, $event) = @_; my @to = $event->to; my ($them, $me) = ($event->nick, $self->nick); ($msg) = ($event->args); $name = $event->nick; #$msg = $arg; $post = 6; # Note that $event->to() returns a list (or arrayref, in scalar # context) of the message's recipients, since there can easily be # more than one. print "<$them> $msg\n"; }

In reply to Tweaking an IRC Client by deadpickle

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.