O'Reilly Hacks
oreilly.comO'Reilly NetworkSafari BookshelfConferences Sign In/My Account | View Cart   
Book List Learning Lab PDFs O'Reilly Gear Newsletters Press Room Jobs  


 
Buy the book!
IRC Hacks
By Paul Mutton
July 2004
More Info

HACK
#29
Make IRC Talk
Even when you can't keep your IRC client in view, keep track of IRC by making your IRC client talk to you
The Code
[Discuss (0) | Link to this hack]

The Code

So you don't block irssi while pushing data to the Festival server, you must spawn a helper in a child process to take care of things. You can give it everything through a pipe and close it if the child dies (you probably want to restart it in case the settings change).

# Talking irssi gadget (c) Petr Baudis <pasky@ucw.cz>, BSD licence.

use strict;

use vars qw($forked $wh $type $lang);

use Irssi;
use Irssi::Irc;
use Speech::Synthesiser;

# Spawn a helper which will feed our Festival backend, so that we do not
# block the main irssi process while pushing data all around.
sub fork_me {
  my ($rh, $pid);
  pipe($rh, $wh);
  $forked = 1;
  $pid = fork( );
  if ($pid > 0) {
    # The main irssi process
    close $rh;
    # This makes sure we do not get a zombie
    Irssi::pidwait_add($pid);
    return;
  } else {
    # The helper child
    close($wh);
    my $synth = new Speech::Synthesiser(-type => $type);
    start $synth;
    if ($lang) { voice $synth $lang; }
    while (my $in = <$rh>) {
      chomp $in;
      speak $synth $in;
    }
    stop $synth;
    close($rh);
    POSIX::_exit(0);
  }
}

# The incoming message event handler.
sub event_privmsg {
  my ($server, $data, $nick, $address) = @_;
  my ($msgtarget, $text) = split(/ :/, $data, 2);
  my (@channels) = split(/\s+/, Irssi::settings_get_str('speech_channels'));

  # The ~ substitution
  return unless (grep {s/^~$/$server->{nick}/x; $_ eq $msgtarget} @channels);

  # Restart the backend if something changed.
  my ($otype, $olang) = ($type, $lang);
  $type = Irssi::settings_get_str('speech_backend');
  $lang = Irssi::settings_get_str('speech_language');
  if ($forked and ($type ne $otype or $lang ne $olang)) {
    print $wh "\n";
    close($wh);
    $forked = 0;
  }
  if (!$forked) {
    fork_me( );
  }

  # Some emoticon replacements (e.g. ":-)"->"hehe!"
  # add your own if you need more!
  $text =~ s/:.?\)/hehe!/g;
  $text =~ s/:.?\(/sniff/g;

  # The exclamation point helps to get the right intonation.
  print $wh "$nick! $text\n";
}

# Our command interface.
sub cmd_speech {
  my ($cmd) = @_;
  if ($cmd =~ /^languages/i) {
    my $synth = new Speech::Synthesiser(
                      -type => Irssi::settings_get_str('speech_backend'));
    start $synth;
    my @voices = voice_list $synth;
    Irssi::print("These languages are supported: @voices");
    stop $synth;
  }
}

Irssi::command_bind('speech', \&cmd_speech);
Irssi::signal_add("event privmsg", "event_privmsg");
Irssi::settings_add_str('speech', 'speech_backend', 'Festival');
Irssi::settings_add_str('speech', 'speech_language', '');
Irssi::settings_add_str('speech', 'speech_channels', '~ #irchacks');


O'Reilly Home | Privacy Policy

© 2007 O'Reilly Media, Inc.
Website: | Customer Service: | Book issues:

All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.