1 from Plugins.Plugin import PluginDescriptor
3 from Tools import Notifications
4 from netgrowl import GrowlRegistrationPacket, GrowlNotificationPacket, \
5 GROWL_UDP_PORT, md5_constructor
6 from twisted.internet.protocol import DatagramProtocol
7 from twisted.internet import reactor
8 from struct import unpack
10 from Screens.Setup import SetupSummary
11 from Screens.Screen import Screen
12 from Screens.MessageBox import MessageBox
13 from Components.ActionMap import ActionMap
14 from Components.config import config, getConfigListEntry, ConfigSubsection, \
15 ConfigText, ConfigPassword, ConfigYesNo
16 from Components.ConfigList import ConfigListScreen
18 config.plugins.growlee = ConfigSubsection()
19 config.plugins.growlee.enable_incoming = ConfigYesNo(default=False)
20 config.plugins.growlee.enable_outgoing = ConfigYesNo(default=False)
21 config.plugins.growlee.address = ConfigText(fixed_size=False)
22 config.plugins.growlee.password = ConfigPassword()
24 class GrowleeConfiguration(Screen, ConfigListScreen):
25 skin = """<screen title="Growlee Configuration" position="75,155" size="565,280">
26 <widget name="config" position="5,5" size="555,100" scrollbarMode="showOnDemand" />
29 def __init__(self, session):
30 Screen.__init__(self, session)
33 self.setup_title = "Growlee Configuration"
34 self.onChangedEntry = []
37 self["actions"] = ActionMap(["SetupActions"],
39 "cancel": self.keySave,
43 ConfigListScreen.__init__(
46 getConfigListEntry(_("Receive Notifications?"), config.plugins.growlee.enable_incoming),
47 getConfigListEntry(_("Send Notifications?"), config.plugins.growlee.enable_outgoing),
48 getConfigListEntry(_("Address"), config.plugins.growlee.address),
49 getConfigListEntry(_("Password"), config.plugins.growlee.password),
52 on_change=self.changed
59 for x in self.onChangedEntry:
65 def getCurrentEntry(self):
66 return self["config"].getCurrent()[0]
68 def getCurrentValue(self):
69 return str(self["config"].getCurrent()[1].getText())
71 def createSummary(self):
75 if self["config"].isChanged():
80 if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
81 port = reactor.listenUDP(GROWL_UDP_PORT, growlProtocolOneWrapper)
86 def configuration(session, **kwargs):
87 session.open(GrowleeConfiguration)
89 class GrowlProtocolOneWrapper(DatagramProtocol):
90 def startProtocol(self):
91 if config.plugins.growlee.enable_outgoing.value:
92 addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
93 p = GrowlRegistrationPacket(password=config.plugins.growlee.password.value)
95 self.transport.write(p.payload(), addr)
97 def sendNotification(self, *args, **kwargs):
98 if not self.transport or not config.plugins.growlee.enable_outgoing.value:
101 addr = (config.plugins.growlee.address.value, GROWL_UDP_PORT)
102 p = GrowlNotificationPacket(*args, **kwargs)
103 self.transport.write(p.payload(), addr)
105 def datagramReceived(self, data, addr):
107 if Len < 16 or not config.plugins.growlee.enable_incoming.value:
111 password = config.plugins.growlee.password.value
112 checksum = md5_constructor()
113 checksum.update(data[:-16])
115 checksum.update(password)
116 if digest != checksum.digest():
120 if data[1] == '\x01':
121 nlen, tlen, dlen, alen = unpack("!HHHH",str(data[4:12]))
122 notification, title, description = unpack(("%ds%ds%ds") % (nlen, tlen, dlen), data[12:Len-alen-16])
124 # XXX: we should add a proper fix :-)
125 Notifications.notificationAdded.remove(gotNotification)
126 Notifications.AddPopup(
127 title + '\n' + description,
128 MessageBox.TYPE_INFO,
131 Notifications.notificationAdded.insert(0, gotNotification)
133 # TODO: do we want to handle register packets? :-)
135 growlProtocolOneWrapper = GrowlProtocolOneWrapper()
138 def gotNotification():
139 notifications = Notifications.notifications
141 _, screen, args, kwargs, _ = notifications[-1]
142 if screen is MessageBox:
145 description = kwargs["text"]
147 description = args[0]
149 growlProtocolOneWrapper.sendNotification(title="Dreambox", description=description, password=config.plugins.growlee.password.value)
151 def autostart(**kwargs):
152 if config.plugins.growlee.enable_incoming.value or config.plugins.growlee.enable_outgoing.value:
154 port = reactor.listenUDP(GROWL_UDP_PORT, growlProtocolOneWrapper)
156 # NOTE: we need to be the first one to be notified since other listeners
157 # may remove the notifications from the list for good
158 Notifications.notificationAdded.insert(0, gotNotification)
160 def Plugins(**kwargs):
163 where=PluginDescriptor.WHERE_SESSIONSTART,
168 description=_("Configure Growlee"),
169 where=PluginDescriptor.WHERE_PLUGINMENU,