I did not like libnotify, so I created an UDP server in Python and a client application for irssi. Note that this answer applies to the original requirements in revision 1, it does not have text notification.
Client
##
## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
## /load perl
## /script load notifyudp
##
use strict;
use Irssi;
use IO::Socket;
use vars qw($VERSION %IRSSI);
$VERSION = "0.02";
%IRSSI = (
authors => 'Lekensteyn',
contact => 'lekensteyn@gmail.com',
name => 'notifyudp.pl',
description => 'Send a UDP signal to a remote machine',
license => 'GPLv3+'
);
Irssi::settings_add_str('notifyudp', 'notifyudp_ip_addr', '');
# port 0 = disabled
Irssi::settings_add_int('notifyudp', 'notifyudp_port', 0);
Irssi::settings_add_bool('notifyudp', 'notifyudp_auto_start', 0);
my $sock;
sub notify_load {
if ($sock) {
Irssi::print('NotifyUDP: Already connected.');
return;
}
my $ip = Irssi::settings_get_str('notifyudp_ip_addr');
my $port = Irssi::settings_get_int('notifyudp_port');
if (!$port || !$ip) {
Irssi::print('NotifyUDP: No port or host set, /set notifyudp for more information..');
return;
}
if ($port < 1024 || $port > 65535) {
Irssi::print('NotifyUDP: Invalid port, must be 1024 <= port <= 65535, resetting and ignoring.');
Irssi::settings_set_int('notifyudp_port', 0);
return;
}
$sock = new IO::Socket::INET(
PeerAddr => $ip,
PeerPort => $port,
Proto => 'udp',
Timeout => 1
);
Irssi::print("NotifyUDP: IP $ip will be notified on port $port.");
}
sub notify {
if ($sock) {
print $sock "M";
}
}
sub notify_stop {
if ($sock) {
Irssi::print("NotifyUDP: Stopping.");
print $sock "S";
$sock = undef;
} else {
Irssi::print("NotifyUDP: not active.");
}
}
sub cmd_notifyudp {
my ($cmd) = @_;
if ($cmd eq 'start') {
notify_load();
} elsif ($cmd eq 'stop') {
notify_stop();
} else {
Irssi::print('NotifyUDP: Usage: /notifyudp [start|stop]');
}
}
Irssi::command_bind('notifyudp', 'cmd_notifyudp');
Irssi::signal_add('print text', 'notify');
Irssi::signal_add('message private', 'notify');
Irssi::signal_add('dcc request', 'notify');
if (Irssi::settings_get_bool('notifyudp_auto_start')) {
Irssi::print('NotifyUDP: automatic connection with the sound server is enabled.');
notify_load();
} else {
Irssi::print('NotifyUDP: automatic connection with the sound server is disabled.');
}
Server
When started, it listens on all addresses, port 3533. If it receives a UDP packet "M", it plays /usr/share/sounds/KDE-Im-Irc-Event.ogg using paplay ("PulseAudio play"). On receiving S, it quits the server. Since it's open-source, you are free to remove this.
#!/usr/bin/env python
# udpsoundserver.py
"""Listen on a UDP port and play a sound when 'M' is received
Starts the server listening on UDP port PORT (3533 by default) on address HOST
(by default all addresses). Valid commands are:
M - play Music
S - Stop the server
"""
try:
import socketserver
except ImportError:
import SocketServer as socketserver
from os import system,getpid
import threading
import sys
# leave it empty to listen on all addresses
HOST = ""
PORT = 3533
class UDPSvr(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0]
if sys.version >= '3':
data = str(data, "ISO-8859-1")
data = data.strip()
if data == "M":
ding.dong()
elif data == "S":
ding.die()
class Worker(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
def run(self):
server.serve_forever();
class Handler(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.play = False
self.must_die = False
def run(self):
self.event = threading.Event()
while True:
self.event.wait(1.)
if self.event.isSet():
if self.play:
print("Playing...")
system("paplay /usr/share/sounds/KDE-Im-Irc-Event.ogg")
# no else if to allow shutdown signals
if self.must_die:
print("Shutting down...")
server.shutdown()
break
self.play = False
self.event.clear()
def dong(self):
self.play = True
self.event.set()
def die(self):
self.must_die = True
self.event.set()
def ca(num, x):
print("Caught SIGINT, shutting down...")
ding.die()
import signal
if __name__ == "__main__":
print("My PID is: " + str(getpid()))
if len(sys.argv) > 1:
HOST = sys.argv[1]
if len(sys.argv) > 2:
PORT = int(sys.argv[2])
print("Host: " + HOST)
print("Port: " + str(PORT))
server = socketserver.UDPServer((HOST, PORT), UDPSvr)
ding = Handler()
signal.signal(signal.SIGINT, ca)
worker = Worker()
ding.start()
worker.start()
# might not be the cleanest, but it allows Ctrl + C
while ding.isAlive():
ding.join(3600)
The sequence of starting the remote server becomes:
screen -dm path/to/udpsoundserver.py
ssh -R 5355:localhost:5355
After logging in, I run:
screen -t irssi irssi
Should you need to reconnect later:
screen -r irssi
After starting irssi, you need to set the host and port:
/set notifyudp_ip_addr 127.0.0.1
/set notifyudp_port 5355
To make it connect automatically on startup:
/set notifyudp_auto_start 1
The first time, you need to start Notify UDP manually since it was not auto started yet:
/notifyudp start
Todo:
- make the soundserver stop on disconnect
- allow for skipping some kind of messages (e.g. leave / join)
- allow for skipping channels