be76f79e12987842c4a3a1fe2481cf0f99c88a87
[enigma2.git] / lib / python / Plugins / Extensions / FritzCall / plugin.py
1 from Screens.Screen import Screen
2 from Screens.MessageBox import MessageBox
3 from Components.ActionMap import ActionMap
4 from Plugins.Plugin import PluginDescriptor
5 from Tools import Notifications
6
7 from twisted.internet import reactor
8 from twisted.internet.protocol import ReconnectingClientFactory
9 from twisted.protocols.basic import LineReceiver
10
11 my_global_session = None
12
13 from Components.config import config, ConfigSubsection, ConfigIP, ConfigEnableDisable, getConfigListEntry
14 from Components.ConfigList import ConfigListScreen
15
16 config.plugins.FritzCall = ConfigSubsection()
17 config.plugins.FritzCall.hostname = ConfigIP(default = [192,168,178,254])
18 config.plugins.FritzCall.enable = ConfigEnableDisable(default = False)
19
20 class FritzCallSetup(ConfigListScreen, Screen):
21         skin = """
22                 <screen position="100,100" size="550,400" title="FritzCall Setup" >
23                 <widget name="config" position="20,10" size="460,350" scrollbarMode="showOnDemand" />
24                 </screen>"""
25
26
27         def __init__(self, session, args = None):
28                 Screen.__init__(self, session)
29                 self.onClose.append(self.abort)
30                 
31                 # nun erzeugen wir eine liste von elementen fuer die menu liste.
32                 self.list = [ ]
33                 self.list.append(getConfigListEntry(_("Call monitoring"), config.plugins.FritzCall.enable))
34                 self.list.append(getConfigListEntry(_("Fritz!Box FON IP address"), config.plugins.FritzCall.hostname))
35                 ConfigListScreen.__init__(self, self.list)
36
37                 # DO NOT ASK.
38                 self["setupActions"] = ActionMap(["SetupActions"],
39                 {
40                         "save": self.save,
41                         "cancel": self.cancel,
42                         "ok": self.save,
43                 }, -2)
44
45         def abort(self):
46                 print "aborting"
47
48         def save(self):
49                 for x in self["config"].list:
50                         x[1].save()
51                 if fritz_call is not None:
52                         fritz_call.connect()
53                 self.close()
54
55         def cancel(self):
56                 for x in self["config"].list:
57                         x[1].cancel()
58                 self.close()
59
60 class FritzProtocol(LineReceiver):
61         delimiter = "\r\n"
62         
63         def lineReceived(self, line):
64
65 #15.07.06 00:38:54;CALL;1;4;<provider>;<callee>;
66 #15.07.06 00:38:58;DISCONNECT;1;0;
67 #15.07.06 00:39:22;RING;0;<caller>;<outgoing msn>;
68 #15.07.06 00:39:27;DISCONNECT;0;0;
69
70                 a = line.split(';')
71                 (date, event) = a[0:2]
72                 line = a[2]
73                 
74                 if event == "RING":
75                         phone = a[4]
76                         number = a[3]
77                         text = _("incoming call!\n%s calls on %s!") % (number, phone)
78                         timeout = 10
79                 elif event == "DISCONNECT":
80                         Notifications.RemovePopup("FritzCall_%s" % line)
81                         return
82                 else:   
83                         return
84                 
85                 Notifications.AddPopup(text=text, type=MessageBox.TYPE_INFO, timeout=timeout, id="FritzCall_%s" % line)
86
87 class FritzClientFactory(ReconnectingClientFactory):
88
89         initialDelay = 20
90         maxDelay = 500
91         
92         def __init__(self):
93                 self.hangup_ok = False
94
95         def startedConnecting(self, connector):
96                 Notifications.AddPopup(text=_("Connecting to Fritz!Box..."), type=MessageBox.TYPE_INFO, timeout=2, id="FritzCallConnect")
97
98         def buildProtocol(self, addr):
99                 Notifications.AddPopup(text=_("Connected to Fritz!Box!"), type=MessageBox.TYPE_INFO, timeout=2, id="FritzCallConnect")
100                 self.resetDelay()
101                 return FritzProtocol()
102
103         def clientConnectionLost(self, connector, reason):
104                 if not self.hangup_ok:
105                         Notifications.AddPopup(text=_("Disconnected from\nFritz!Box! (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=4, id="FritzCallConnect")
106                 ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
107
108         def clientConnectionFailed(self, connector, reason):
109                 Notifications.AddPopup(text=_("Connection to Fritz!Box\nfailed! (%s)\nretrying...") % reason.getErrorMessage(), type=MessageBox.TYPE_INFO, timeout=4, id="FritzCallConnect")
110                 ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
111
112 class FritzCall:
113         def __init__(self):
114                 self.dialog = None
115                 self.d = None
116                 self.connect()
117                 
118         def connect(self):      
119                 self.abort()
120                 if config.plugins.FritzCall.enable.value:
121                         f = FritzClientFactory()
122                         self.d = (f, reactor.connectTCP("%d.%d.%d.%d" % tuple(config.plugins.FritzCall.hostname.value), 1012, f))
123
124         def shutdown(self):
125                 self.abort()
126
127         def abort(self):
128                 if self.d is not None:
129                         self.d[0].hangup_ok = True 
130                         self.d[0].stopTrying()
131                         self.d[1].disconnect()
132                         self.d = None
133
134 def main(session, **kwargs):
135         session.open(FritzCallSetup)
136
137 fritz_call = None
138
139 def autostart(reason, **kwargs):
140         global fritz_call
141         
142         # ouch, this is a hack  
143         if kwargs.has_key("session"):
144                 global my_global_session
145                 my_global_session = kwargs["session"]
146                 return
147         
148         print "autostart"
149         if reason == 0:
150                 fritz_call = FritzCall()
151         elif reason == 1:
152                 fritz_call.shutdown()
153                 fritz_call = None
154
155 def Plugins(**kwargs):
156         return [ PluginDescriptor(name="FritzCall", description="Display Fritzbox-Fon calls on screen", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
157                 PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart) ]