diff --git a/fnotify.pl b/fnotify.pl index 3d19920..7438dfb 100644 --- a/fnotify.pl +++ b/fnotify.pl @@ -1,28 +1,62 @@ use strict; use Irssi; use vars qw($VERSION %IRSSI); +use FindBin; +use POSIX; -$VERSION = "3.1-daemonise"; +$VERSION = "4.0"; %IRSSI = ( authors => 'Ritchie Cunningham', contact => 'ritchie@ritchiecunningham.co.uk', name => 'fnotify', - description => 'Sends notify-send notifications for private messages and highlights. Optionally uses festival for voice.', + description => 'Sends desktop and audio notifications for private messages and highlights.', license => 'Public Domain', ); # --- Global variables to hold raw message data between signals. --- my ($last_public_msg, $last_public_nick, $last_public_target); - # --- Configuration. --- my $festival_voice = '(voice_us1_mbrola)'; # --- Core Functions. --- sub notify { my ($title, $message) = @_; + + # --- Visual desktop notification. --- system("notify-send", "-i", "irssi", $title, $message); + # --- Play a notification sound file. --- + if(Irssi::settings_get_bool('fnotify_sound_enabled')) { + my $sound_player = Irssi::settings_get_str('fnotify_sound_player'); + my $sound_file = Irssi::settings_get_str('fnotify_sound_file'); + + if($sound_player && $sound_file) { + # If the path isn't absolute, prepend the script's directory. + # Note: For best results, set the full absolute path in with /set command. + if($sound_file !~ m#^/#) { + $sound_file = "$FindBin::Bin/$sound_file"; + } + + # Use a non-blocking fork to play sound without freezing Irssi. + my $pid = fork(); + if(!defined $pid) { + Irssi::print("fnotify: Could not fork() to play sound: $!", MSGLEVEL_CLIENTERROR); + return; + } + + if($pid == 0) { + # Child process. Detach and execute the sound player. + close STDIN; close STDOUT; close STDERR; + POSIX::setsid(); + exec($sound_player, $sound_file); + exit(127); # Kill child if exec fails for any reason. + } + # Aaaand back with the parent. + } + } + + # --- TTS using festival. --- if(Irssi::settings_get_bool('festival_enabled')) { my $text_to_speak = "$title, $message"; @@ -49,8 +83,6 @@ sub notify { } # --- Signal Handlers. --- - -# Private messages are simple and clean. No theme conflicts. sub private_message_handler { my ($server, $msg, $nick, $address) = @_; return if($nick =~ /^(NickServ|ChanServ|MemoServ)$/i); @@ -67,23 +99,19 @@ sub public_message_handler { sub print_text_handler { my ($dest, $text, $stripped) = @_; - - # Check if the level is a highlight and the target matches the one we just saved. - # The target check prevents us from misfiring on other window text. if(($dest->{level} & Irssi::MSGLEVEL_HILIGHT) && ($dest->{target} eq $last_public_target)) { - # Make sure the data from the first signal is actually there. return unless defined $last_public_nick; - - # Use the CLEAN data we saved to build the notification! notify("Mentioned by $last_public_nick in $last_public_target", $last_public_msg); - - # Clear the variables so we don't accidentally re-use them. undef $last_public_nick; } } # --- Settings and Signal Registration. --- Irssi::settings_add_bool('lookandfeel', 'festival_enabled', 0); +Irssi::settings_add_bool('lookandfeel', 'fnotify_sound_enabled', 1); +Irssi::settings_add_str('lookandfeel', 'fnotify_sound_player', 'mpg123'); +Irssi::settings_add_str('lookandfeel', 'fnotify_sound_file', 'msg_notification.mp3'); + # Register all three handlers. Irssi::signal_add('message private', 'private_message_handler'); diff --git a/msg_notification.mp3 b/msg_notification.mp3 new file mode 100644 index 0000000..5cdb693 Binary files /dev/null and b/msg_notification.mp3 differ