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