rework backends and split them up,
authorMoritz Venn <ritzmo@users.schwerkraft.elitedvb.net>
Fri, 22 Jan 2010 18:32:33 +0000 (18:32 +0000)
committerMoritz Venn <ritzmo@users.schwerkraft.elitedvb.net>
Fri, 22 Jan 2010 18:32:33 +0000 (18:32 +0000)
allow to set a minimum level (yes/no..error -> -1..2)

growlee/src/GrowlTalk.py [new file with mode: 0644]
growlee/src/GrowleeConnection.py [new file with mode: 0644]
growlee/src/Prowl.py [new file with mode: 0644]
growlee/src/SNP.py [new file with mode: 0644]
growlee/src/__init__.py
growlee/src/plugin.py

diff --git a/growlee/src/GrowlTalk.py b/growlee/src/GrowlTalk.py
new file mode 100644 (file)
index 0000000..9fef12f
--- /dev/null
@@ -0,0 +1,100 @@
+from netgrowl import GrowlRegistrationPacket, GrowlNotificationPacket, \
+               GROWL_UDP_PORT, md5_constructor
+from twisted.internet.protocol import DatagramProtocol
+from twisted.internet import reactor
+from struct import unpack
+
+from Tools import Notifications
+from Components.config import config
+
+from GrowleeConnection import emergencyDisable
+from . import NOTIFICATIONID
+
+class GrowlTalk(DatagramProtocol):
+       addr = None
+
+       def gotIP(self, ip):
+               self.addr = (ip, GROWL_UDP_PORT)
+               if config.plugins.growlee.enable_outgoing.value:
+                       p = GrowlRegistrationPacket(application="growlee", password=config.plugins.growlee.password.value)
+                       p.addNotification()
+                       payload = p.payload()
+
+                       self.transport.write(payload, self.addr)
+
+       def noIP(self, error):
+               emergencyDisable()
+
+       def startProtocol(self):
+               reactor.resolve(config.plugins.growlee.address.value).addCallback(self.gotIP).addErrback(self.noIP)
+
+       def sendNotification(self, *args, **kwargs):
+               if not self.transport or not self.addr or not config.plugins.growlee.enable_outgoing.value:
+                       return
+
+               kwargs["application"] = "growlee"
+               kwargs["password"] = config.plugins.growlee.password.value
+               p = GrowlNotificationPacket(*args, **kwargs)
+               payload = p.payload()
+
+               self.transport.write(payload, self.addr)
+
+       def datagramReceived(self, data, addr):
+               if not config.plugins.growlee.enable_incoming.value:
+                       return
+
+               Len = len(data)
+               if Len < 16:
+                       return
+
+               # ver == GROWL_PROTOCOL_VERSION
+               if data[0] != '\x01':
+                       return
+
+               # type == GROWL_TYPE_NOTIFICATION
+               if data[1] == '\x01':
+                       digest = data[-16:]
+                       password = config.plugins.growlee.password.value
+                       checksum = md5_constructor()
+                       checksum.update(data[:-16])
+                       if password:
+                               checksum.update(password)
+                       if digest != checksum.digest():
+                               return
+
+                       nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
+                       notification, title, description = unpack("%ds%ds%ds" % (nlen, tlen, dlen), data[12:Len-alen-16])
+               # type == GROWL_TYPE_NOTIFICATION_NOAUTH
+               elif data[1] == '\x05':
+                       nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
+                       notification, title, description = unpack("%ds%ds%ds" % (nlen, tlen, dlen), data[12:Len-alen])
+               else:
+                       # don't handle any other packet yet
+                       return
+
+               Notifications.AddNotificationWithID(
+                       NOTIFICATIONID,
+                       MessageBox,
+                       text = title + '\n' + description,
+                       type = MessageBox.TYPE_INFO,
+                       timeout = 5,
+                       close_on_any_key = True,
+               )
+
+class GrowlTalkAbstraction:
+       def __init__(self):
+               self.growltalk = GrowlTalk()
+               self.serverPort = reactor.listenUDP(GROWL_UDP_PORT, self.growltalk)
+
+       def sendNotification(self, *args, **kwargs):
+               # map timeout -> sticky
+               if "timeout" in kwargs:
+                       if kwargs["timeout"] == -1:
+                               kwargs["sticky"] = True
+                       del kwargs["timeout"]
+
+               self.growltalk.sendNotification(*args, **kwargs)
+
+       def stop(self):
+               return self.serverPort.stopListening()
+
diff --git a/growlee/src/GrowleeConnection.py b/growlee/src/GrowleeConnection.py
new file mode 100644 (file)
index 0000000..0c10729
--- /dev/null
@@ -0,0 +1,69 @@
+from Components.config import config
+from Tools import Notifications
+from Screens.MessageBox import MessageBox
+
+from . import NOTIFICATIONID
+
+def emergencyDisable(*args, **kwargs):
+       global growleeConnection
+       if growleeConnection:
+               growleeConnection.stop()
+
+       if gotNotification in Notifications.notificationAdded:
+               Notifications.notificationAdded.remove(gotNotification)
+       Notifications.AddPopup(
+               _("Network error.\nDisabling Growlee until next restart!"),
+               MessageBox.TYPE_ERROR,
+               10
+       )
+
+def gotNotification():
+       notifications = Notifications.notifications
+       if notifications:
+               _, screen, args, kwargs, id = notifications[-1]
+               if screen is MessageBox and id != NOTIFICATIONID and id not in config.plugins.growlee.blacklist.value:
+
+                       # NOTE: priority is in [-2; 2] but type is [0; 3] so map it
+                       # XXX: maybe priority==type-2 would be more appropriate
+                       priority = kwargs.get("type", 0) - 1
+                       timeout = kwargs.get("timeout", -1)
+
+                       if "text" in kwargs:
+                               description = kwargs["text"]
+                       else:
+                               description = args[0]
+                       description = description.decode('utf-8')
+
+                       growleeConnection.sendNotification(title="Dreambox", description=description, priority=priority, timeout=timeout)
+
+class GrowleeConnection:
+       connection = None
+
+       def sendNotification(self, title="Dreambox", description='', priority=-1, timeout = -1):
+               if self.connection and not priority < config.plugins.growlee.level.value:
+                       self.connection.sendNotification(title=title, description=description, priority=priority, timeout=timeout)
+
+       def listen(self):
+               if self.connection:
+                       return
+
+               proto = config.plugins.growlee.protocol.value
+               if proto == "prowl":
+                       from Prowl import ProwlAPI
+                       self.connection = ProwlAPI()
+               elif proto == "growl":
+                       from GrowlTalk import GrowlTalkAbstraction
+                       self.connection = GrowlTalkAbstraction()
+               else: # proto == "snarl":
+                       from SNP import SnarlNetworkProtocolAbstraction
+                       self.connection = SnarlNetworkProtocolAbstraction()
+
+       def stop(self):
+               if self.connection:
+                       d = self.connection.stop()
+                       self.connection = None
+                       return d
+               return None
+
+growleeConnection = GrowleeConnection()
+
diff --git a/growlee/src/Prowl.py b/growlee/src/Prowl.py
new file mode 100644 (file)
index 0000000..a9ee1f1
--- /dev/null
@@ -0,0 +1,31 @@
+from twisted.web.client import getPage
+from twisted.internet.defer import Deferred
+from twisted.internet import reactor
+from urllib import urlencode
+
+from Components.config import config
+
+from GrowleeConnection import emergencyDisable
+from . import NOTIFICATIONID
+
+class ProwlAPI:
+       def sendNotification(self, title='No title.', description='No message.', priority=0, timeout=-1):
+               if not config.plugins.growlee.enable_outgoing.value:
+                       return
+
+               headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
+               data = {
+                       'apikey': config.plugins.growlee.prowl_api_key.value,
+                       'application': "growlee",
+                       'event': title,
+                       'description': description,
+                       'priority': priority,
+               }
+
+               getPage('https://prowl.weks.net/publicapi/add/', method = 'POST', headers = headers, postdata = urlencode(data)).addErrback(emergencyDisable)
+
+       def stop(self):
+               defer = Deferred()
+               reactor.callLater(1, defer.callback, True)
+               return defer
+
diff --git a/growlee/src/SNP.py b/growlee/src/SNP.py
new file mode 100644 (file)
index 0000000..9b0c3d3
--- /dev/null
@@ -0,0 +1,184 @@
+from netgrowl import GROWL_UDP_PORT
+from twisted.internet.defer import Deferred
+from twisted.internet.protocol import ClientFactory, ServerFactory
+from twisted.internet import reactor
+from twisted.protocols.basic import LineReceiver
+
+from Tools import Notifications
+from Components.config import config
+
+from GrowleeConnection import emergencyDisable
+from . import NOTIFICATIONID
+
+class SnarlNetworkProtocol(LineReceiver):
+       def __init__(self, client = False):
+               self.client = client
+
+       def connectionMade(self):
+               self.factory.addClient(self)
+               if self.client:
+                       payload = "type=SNP#?version=1.0#?action=register#?app=growlee"
+                       self.sendLine(payload)
+
+                       payload = "type=SNP#?version=1.0#?action=add_class#?app=growlee#?class=growleeClass#?title=Notifications from your Dreambox"
+                       self.sendLine(payload)
+
+       def connectionLost(self, reason):
+               self.factory.removeClient(self)
+
+       def stop(self):
+               if self.client:
+                       payload = "type=SNP#?version=1.0#?action=unregister#?app=growlee"
+                       self.sendLine(payload)
+
+               self.transport.loseConnection()
+
+       def sendNotification(self, title='No title.', description='No message.', timeout=1):
+               if not self.client or not self.transport:
+                       return
+
+               payload = "type=SNP#?version=1.0#?action=notification#?app=growlee#?class=growleeClass#?title=%s#?text=%s#?timeout=%d" % (title, description, timeout)
+               self.sendLine(payload)
+
+       def lineReceived(self, data):
+               if self.client or not self.transport:
+                       return
+
+               Len = len(data)
+               if Len < 23 or not data[:23] == "type=SNP#?version=1.0#?":
+                       return
+
+               items = data[23:].split('#?')
+
+               title = ''
+               description = ''
+               timeout = 5
+               for item in items:
+                       key, value = item.split('=')
+                       if key == "action":
+                               if value == "unregister":
+                                       payload = "SNP/1.0/0/OK"
+                                       self.sendLine(payload)
+                                       self.transport.loseConnection()
+                                       return
+                               elif value != "notification":
+                                       # NOTE: we pretend to handle&accept pretty much everything one throws at us
+                                       payload = "SNP/1.0/0/OK"
+                                       self.sendLine(payload)
+                                       return
+                       elif key == "title":
+                               title = value
+                       elif key == "text":
+                               description = value
+                       elif key == "timeout":
+                               timeout = int(value)
+
+               Notifications.AddNotificationWithID(
+                       NOTIFICATIONID,
+                       MessageBox,
+                       text = title + '\n' + description,
+                       type = MessageBox.TYPE_INFO,
+                       timeout = timeout,
+                       close_on_any_key = True,
+               )
+
+               # return ok
+               payload = "SNP/1.0/0/OK"
+               self.sendLine(payload)
+
+class SnarlNetworkProtocolClientFactory(ClientFactory):
+       client = None
+
+       def buildProtocol(self, addr):
+               p = SnarlNetworkProtocol(client = True)
+               p.factory = self
+               return p
+
+       def sendNotification(self, title='No title.', description='No message.', priority=0, timeout=-1):
+               if self.client:
+                       title = title.decode('utf-8', 'ignore').encode('iso8859-15', 'ignore')
+                       description = description.decode('utf-8', 'ignore').encode('iso8859-15', 'ignore')
+
+                       # NOTE: timeout = 0 means sticky, so add one second to map -1 to 0 and make 0 non-sticky
+                       if timeout < 1:
+                               timeout += 1
+
+                       self.client.sendNotification(title=title, description=description, timeout=timeout)
+
+       def addClient(self, client):
+               self.client = client
+
+       def removeClient(self, client):
+               self.client = None
+
+class SnarlNetworkProtocolServerFactory(ServerFactory):
+       protocol = SnarlNetworkProtocol
+
+       def __init__(self):
+               self.clients = []
+
+       def addClient(self, client):
+               self.clients.append(client)
+
+       def removeClient(self, client):
+               self.clients.remove(client)
+
+       def sendNotification(self, *args, **kwargs):
+               pass
+
+       def stopFactory(self):
+               for client in self.clients:
+                       client.stop()
+
+class SnarlNetworkProtocolAbstraction:
+       clientPort = None
+       serverPort = None
+       pending = 0
+
+       def __init__(self):
+               self.clientFactory = SnarlNetworkProtocolClientFactory()
+               self.serverFactory = SnarlNetworkProtocolServerFactory()
+
+               if config.plugins.growlee.enable_outgoing.value:
+                       reactor.resolve(config.plugins.growlee.address.value).addCallback(self.gotIP).addErrback(self.noIP)
+
+               if config.plugins.growlee.enable_incoming.value:
+                       self.serverPort = reactor.listenTCP(GROWL_UDP_PORT, self.serverFactory)
+                       self.pending += 1
+
+       def gotIP(self, ip):
+               self.clientPort = reactor.connectTCP(ip, GROWL_UDP_PORT, self.clientFactory)
+               self.pending += 1
+
+       def noIP(self, error):
+               emergencyDisable()
+
+       def sendNotification(self, *args, **kwargs):
+               self.clientFactory.sendNotification(*args, **kwargs)
+
+       def maybeClose(self, resOrFail, defer = None):
+               self.pending -= 1
+               if self.pending == 0:
+                       if defer:
+                               defer.callback(True)
+
+       def stop(self):
+               defer = Deferred()
+               if self.clientPort:
+                       d = self.clientPort.disconnect()
+                       if d:
+                               d.addBoth(self.maybeClose, defer = defer)
+                       else:
+                               self.pending -= 1
+
+               if self.serverPort:
+                       d = self.serverPort.stopListening()
+                       if d:
+                               d.addBoth(self.maybeClose, defer = defer)
+                       else:
+                               self.pending -= 1
+
+               if self.pending == 0:
+                       reactor.callLater(1, defer.callback, True)
+               return defer
+
index e69de29..5a9e23e 100644 (file)
@@ -0,0 +1,2 @@
+NOTIFICATIONID = 'GrowleeReceivedNotification'
+
index efb323c..d8056a9 100644 (file)
@@ -1,24 +1,19 @@
 from Plugins.Plugin import PluginDescriptor
 
 from Tools import Notifications
-from netgrowl import GrowlRegistrationPacket, GrowlNotificationPacket, \
-               GROWL_UDP_PORT, md5_constructor
-from twisted.internet.protocol import DatagramProtocol
-from twisted.internet import reactor
-from twisted.web.client import getPage
-from struct import unpack
-from socket import gaierror
-from urllib import urlencode
 
 from Screens.Setup import SetupSummary
 from Screens.Screen import Screen
-from Screens.MessageBox import MessageBox
 from Components.ActionMap import ActionMap
 from Components.config import config, getConfigListEntry, ConfigSubsection, \
                ConfigText, ConfigPassword, ConfigYesNo, ConfigSelection, ConfigSet
 from Components.ConfigList import ConfigListScreen
 from Components.Sources.StaticText import StaticText
 
+from GrowleeConnection import gotNotification, emergencyDisable, growleeConnection
+
+from . import NOTIFICATIONID
+
 config.plugins.growlee = ConfigSubsection()
 config.plugins.growlee.enable_incoming = ConfigYesNo(default=False)
 config.plugins.growlee.enable_outgoing = ConfigYesNo(default=False)
@@ -26,10 +21,9 @@ config.plugins.growlee.address = ConfigText(fixed_size=False)
 config.plugins.growlee.password = ConfigPassword()
 config.plugins.growlee.prowl_api_key = ConfigText(fixed_size=False)
 config.plugins.growlee.protocol = ConfigSelection(default="growl", choices = [("growl", "Growl"), ("snarl", "Snarl"), ("prowl", "Prowl")])
+config.plugins.growlee.level = ConfigSelection(default=-1, choices = [(-1, _("Low (Yes/No)")), (0, _("Normal (Information)")), (1, _("High (Warning)")), (2, _("Highest (Emergency)"))])
 config.plugins.growlee.blacklist = ConfigSet(choices = [])
 
-NOTIFICATIONID = 'GrowleeReceivedNotification'
-
 class GrowleeConfiguration(Screen, ConfigListScreen):
        def __init__(self, session):
                Screen.__init__(self, session)
@@ -70,17 +64,22 @@ class GrowleeConfiguration(Screen, ConfigListScreen):
        def setupList(self, *args):
                l = [
                        getConfigListEntry(_("Type"), config.plugins.growlee.protocol),
+                       getConfigListEntry(_("Minimum Priority"), config.plugins.growlee.level),
                        getConfigListEntry(_("Send Notifications?"), config.plugins.growlee.enable_outgoing),
                ]
 
-               if config.plugins.growlee.protocol.value == "prowl":
+               proto = config.plugins.growlee.protocol.value
+               if proto ==  "prowl":
                        l.append(getConfigListEntry(_("API Key"), config.plugins.growlee.prowl_api_key))
                else:
                        l.extend((
                                getConfigListEntry(_("Receive Notifications?"), config.plugins.growlee.enable_incoming),
                                getConfigListEntry(_("Address"), config.plugins.growlee.address),
-                               getConfigListEntry(_("Password"), config.plugins.growlee.password),
                        ))
+                       if proto == "growl":
+                               l.append(
+                                       getConfigListEntry(_("Password"), config.plugins.growlee.password)
+                               )
 
                self["config"].list = l
 
@@ -97,19 +96,12 @@ class GrowleeConfiguration(Screen, ConfigListScreen):
 
        def keySave(self):
                if self["config"].isChanged():
-                       global port
-                       if port:
-                               def maybeConnect(*args, **kwargs):
-                                       if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
-                                               doConnect()
+                       def maybeConnect(*args, **kwargs):
+                               if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
+                                       growleeConnection.listen()
 
-                               d = port.stopListening()
-                               if d is not None:
-                                       d.addCallback(maybeConnect).addErrback(emergencyDisable)
-                               else:
-                                       maybeConnect()
-                       elif config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
-                               doConnect()
+                       d = growleeConnection.stop()
+                       d.addCallback(maybeConnect).addErrback(emergencyDisable)
 
                self.saveAll()
                self.close()
@@ -121,205 +113,14 @@ class GrowleeConfiguration(Screen, ConfigListScreen):
 def configuration(session, **kwargs):
        session.open(GrowleeConfiguration)
 
-def doConnect():
-       global port
-       if config.plugins.growlee.protocol.value == "snarl":
-               port = reactor.listenTCP(GROWL_UDP_PORT, growlProtocolOneWrapper)
-       else:
-               port = reactor.listenUDP(GROWL_UDP_PORT, growlProtocolOneWrapper)
-
-def emergencyDisable(*args, **kwargs):
-       global port
-       if port:
-               port.stopListening()
-               port = None
-
-       if gotNotification in Notifications.notificationAdded:
-               Notifications.notificationAdded.remove(gotNotification)
-       Notifications.AddPopup(
-               _("Network error.\nDisabling Growlee!"),
-               MessageBox.TYPE_ERROR,
-               10
-       )
-
-class GrowlProtocolOneWrapper(DatagramProtocol):
-       def startProtocol(self):
-               proto = config.plugins.growlee.protocol.value
-               if config.plugins.growlee.enable_outgoing.value and not proto == "prowl":
-                       addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
-                       if proto == "growl":
-                               p = GrowlRegistrationPacket(application="growlee", password=config.plugins.growlee.password.value)
-                               p.addNotification()
-                               payload = p.payload()
-                       else: #proto == "snarl":
-                               payload = "type=SNP#?version=1.0#?action=register#?app=growlee\r\n"
-                       try:
-                               self.transport.write(payload, addr)
-                       except gaierror:
-                               emergencyDisable()
-
-       def doStop(self):
-               if config.plugins.growlee.enable_outgoing.value and config.plugins.growlee.protocol.value == "snarl":
-                       addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
-                       payload = "type=SNP#?version=1.0#?action=unregister#?app=growlee\r\n"
-                       try:
-                               self.transport.write(payload, addr)
-                       except gaierror:
-                               pass
-               DatagramProtocol.doStop(self)
-
-       def sendNotification(self, *args, **kwargs):
-               if not self.transport or not config.plugins.growlee.enable_outgoing.value:
-                       return
-
-               proto = config.plugins.growlee.protocol.value
-               if proto == "prowl":
-                       headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}
-                       data = {
-                               'apikey': config.plugins.growlee.prowl_api_key.value,
-                               'application': "growlee",
-                               'event': kwargs.get('title', 'No title.'),
-                               'description': kwargs.get('description', 'No message.'),
-                               'priority': kwargs.get('priority', 0),
-                       }
-
-                       getPage('https://prowl.weks.net/publicapi/add/', method = 'POST', headers = headers, postdata = urlencode(data)).addErrback(emergencyDisable)
-               else:
-                       addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
-                       if proto == "growl":
-                               # map timeout -> sticky
-                               if "timeout" in kwargs:
-                                       if kwargs["timeout"] == -1:
-                                               kwargs["sticky"] = True
-                                       del kwargs["timeout"]
-
-                               p = GrowlNotificationPacket(*args, application="growlee", **kwargs)
-                               payload = p.payload()
-                       else: #proto == "snarl":
-                               title = kwargs.get('title', 'No title.')
-                               text = kwargs.get('description', 'No message.')
-                               timeout = kwargs.get('timeout', -1)
-
-                               # NOTE: timeout = 0 means sticky, so add one second to map -1 to 0 and make 0 non-sticky
-                               if timeout < 2:
-                                       timeout += 1
-
-                               payload = "type=SNP#?version=1.0#?action=notification#?app=growlee#?class=growleeClass#?title=%s#?text=%s#?timeout=%d\r\n" % (title, text, timeout)
-                       try:
-                               self.transport.write(payload, addr)
-                       except gaierror:
-                               emergencyDisable()
-
-       def datagramReceived(self, data, addr):
-               proto = config.plugins.growlee.protocol.value
-               if proto == "prowl" or not config.plugins.growlee.enable_incoming.value:
-                       return
-
-               Len = len(data)
-               if proto == "growl":
-                       if Len < 16:
-                               return
-
-                       digest = data[-16:]
-                       password = config.plugins.growlee.password.value
-                       checksum = md5_constructor()
-                       checksum.update(data[:-16])
-                       if password:
-                               checksum.update(password)
-                       if digest != checksum.digest():
-                               return
-
-                       # notify packet
-                       if data[1] == '\x01':
-                               nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
-                               notification, title, description = unpack("%ds%ds%ds" % (nlen, tlen, dlen), data[12:Len-alen-16])
-
-                               Notifications.AddNotificationWithID(
-                                       NOTIFICATIONID,
-                                       MessageBox,
-                                       text = title + '\n' + description,
-                                       type = MessageBox.TYPE_INFO,
-                                       timeout = 5,
-                                       close_on_any_key = True,
-                               )
-
-                       # TODO: do we want to handle register packets? :-)
-               else: #proto == "snarl":
-                       if Len < 23 or not data[:23] == "type=SNP#?version=1.0#?":
-                               return
-
-                       items = data[23:].split('#?')
-
-                       title = ''
-                       description = ''
-                       timeout = 5
-                       for item in items:
-                               key, value = item.split('=')
-                               if key == "action":
-                                       if value != "notification":
-                                               # NOTE: we pretend to handle&accept pretty much everything one throws at us
-                                               addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
-                                               payload = "SNP/1.0/0/OK\r\n"
-                                               try:
-                                                       self.transport.write(payload, addr)
-                                               except gaierror:
-                                                       emergencyDisable()
-                                               return
-                               elif key == "title":
-                                       title = value
-                               elif key == "text":
-                                       description = value
-                               elif key == "timeout":
-                                       timeout = int(value)
-
-                       Notifications.AddNotificationWithID(
-                               NOTIFICATIONID,
-                               MessageBox,
-                               text = title + '\n' + description,
-                               type = MessageBox.TYPE_INFO,
-                               timeout = timeout,
-                               close_on_any_key = True,
-                       )
-
-                       # return ok
-                       addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
-                       payload = "SNP/1.0/0/OK\r\n"
-                       try:
-                               self.transport.write(payload, addr)
-                       except gaierror:
-                               emergencyDisable()
-
-
-growlProtocolOneWrapper = GrowlProtocolOneWrapper()
-port = None
-
-def gotNotification():
-       notifications = Notifications.notifications
-       if notifications:
-               _, screen, args, kwargs, id = notifications[-1]
-               if screen is MessageBox and id != NOTIFICATIONID and id not in config.plugins.growlee.blacklist.value:
-
-                       type = kwargs.get("type", 0)
-                       timeout = kwargs.get("timeout", -1)
-
-                       if "text" in kwargs:
-                               description = kwargs["text"]
-                       else:
-                               description = args[0]
-                       description = description.decode('utf-8')
-
-                       # NOTE: priority is in [-2; 2] but type is [0; 3] so map it
-                       # XXX: maybe priority==type-2 would be more appropriate
-                       growlProtocolOneWrapper.sendNotification(title="Dreambox", description=description, password=config.plugins.growlee.password.value, priority=type-1, timeout=timeout)
-
 def autostart(**kwargs):
-       if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
-               doConnect()
-
        # NOTE: we need to be the first one to be notified since other listeners
        # may remove the notifications from the list for good
        Notifications.notificationAdded.insert(0, gotNotification)
 
+       if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
+               growleeConnection.listen()
+
 def Plugins(**kwargs):
        return [
                PluginDescriptor(