689e87a1f91cefe006f3792db744ce7c85261c5d
[gc-dialer] / src / call_handler.py
1 #!/usr/bin/env python
2
3 from __future__ import with_statement
4 from __future__ import division
5
6 import logging
7
8 from PyQt4 import QtCore
9 import dbus
10 try:
11         import telepathy as _telepathy
12         telepathy = _telepathy
13 except ImportError:
14         _telepathy = None
15
16 import constants
17 import util.tp_utils as telepathy_utils
18 import util.misc as misc_utils
19
20
21 _moduleLogger = logging.getLogger(__name__)
22
23
24 class _MissedCallWatcher(QtCore.QObject):
25
26         callMissed = QtCore.pyqtSignal()
27
28         def __init__(self):
29                 QtCore.QObject.__init__(self)
30                 self._isStarted = False
31
32                 self._newChannelSignaller = telepathy_utils.NewChannelSignaller(self._on_new_channel)
33                 self._outstandingRequests = []
34
35         def start(self):
36                 self._newChannelSignaller.start()
37                 self._isStarted = True
38
39         def stop(self):
40                 if not self._isStarted:
41                         _moduleLogger.info("voicemail monitor stopped without starting")
42                         return
43                 _moduleLogger.info("Stopping voicemail refresh")
44                 self._newChannelSignaller.stop()
45
46                 # I don't want to trust whether the cancel happens within the current
47                 # callback or not which could be the deciding factor between invalid
48                 # iterators or infinite loops
49                 localRequests = [r for r in self._outstandingRequests]
50                 for request in localRequests:
51                         localRequests.cancel()
52
53                 self._isStarted = False
54
55         @misc_utils.log_exception(_moduleLogger)
56         def _on_new_channel(self, bus, serviceName, connObjectPath, channelObjectPath, channelType):
57                 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
58                         return
59
60                 cmName = telepathy_utils.cm_from_path(connObjectPath)
61                 if cmName == constants._telepathy_implementation_name_:
62                         _moduleLogger.debug("Ignoring channels from self to prevent deadlock")
63                         return
64
65                 conn = telepathy.client.Connection(serviceName, connObjectPath)
66                 try:
67                         chan = telepathy.client.Channel(serviceName, channelObjectPath)
68                 except dbus.exceptions.UnknownMethodException:
69                         _moduleLogger.exception("Client might not have implemented a deprecated method")
70                         return
71                 missDetection = telepathy_utils.WasMissedCall(
72                         bus, conn, chan, self._on_missed_call, self._on_error_for_missed
73                 )
74                 self._outstandingRequests.append(missDetection)
75
76         @misc_utils.log_exception(_moduleLogger)
77         def _on_missed_call(self, missDetection):
78                 _moduleLogger.info("Missed a call")
79                 self.callMissed.emit()
80                 self._outstandingRequests.remove(missDetection)
81
82         @misc_utils.log_exception(_moduleLogger)
83         def _on_error_for_missed(self, missDetection, reason):
84                 _moduleLogger.debug("Error: %r claims %r" % (missDetection, reason))
85                 self._outstandingRequests.remove(missDetection)
86
87
88 class _DummyMissedCallWatcher(QtCore.QObject):
89
90         callMissed = QtCore.pyqtSignal()
91
92         def __init__(self):
93                 QtCore.QObject.__init__(self)
94                 self._isStarted = False
95
96         def start(self):
97                 self._isStarted = True
98
99         def stop(self):
100                 if not self._isStarted:
101                         _moduleLogger.info("voicemail monitor stopped without starting")
102                         return
103                 _moduleLogger.info("Stopping voicemail refresh")
104                 self._isStarted = False
105
106
107 if telepathy is not None:
108         MissedCallWatcher = _MissedCallWatcher
109 else:
110         MissedCallWatcher = _DummyMissedCallWatcher
111
112
113 if __name__ == "__main__":
114         pass
115