Enabling support for configuring voicemail check on missed call
[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         import util.tp_utils as telepathy_utils
13         telepathy = _telepathy
14 except ImportError:
15         telepathy = None
16
17 import util.misc as misc_utils
18
19
20 _moduleLogger = logging.getLogger(__name__)
21
22
23 class _FakeSignaller(object):
24
25         def start(self):
26                 pass
27
28         def stop(self):
29                 pass
30
31
32 class _MissedCallWatcher(QtCore.QObject):
33
34         callMissed = QtCore.pyqtSignal()
35
36         def __init__(self):
37                 QtCore.QObject.__init__(self)
38                 self._isStarted = False
39                 self._isSupported = True
40
41                 self._newChannelSignaller = telepathy_utils.NewChannelSignaller(self._on_new_channel)
42                 self._outstandingRequests = []
43
44         @property
45         def isSupported(self):
46                 return self._isSupported
47
48         @property
49         def isStarted(self):
50                 return self._isStarted
51
52         def start(self):
53                 if self._isStarted:
54                         _moduleLogger.info("voicemail monitor already started")
55                         return
56                 try:
57                         self._newChannelSignaller.start()
58                 except RuntimeError:
59                         _moduleLogger.exception("Missed call detection not supported")
60                         self._newChannelSignaller = _FakeSignaller()
61                         self._isSupported = False
62                 self._isStarted = True
63
64         def stop(self):
65                 if not self._isStarted:
66                         _moduleLogger.info("voicemail monitor stopped without starting")
67                         return
68                 _moduleLogger.info("Stopping voicemail refresh")
69                 self._newChannelSignaller.stop()
70
71                 # I don't want to trust whether the cancel happens within the current
72                 # callback or not which could be the deciding factor between invalid
73                 # iterators or infinite loops
74                 localRequests = [r for r in self._outstandingRequests]
75                 for request in localRequests:
76                         localRequests.cancel()
77
78                 self._isStarted = False
79
80         @misc_utils.log_exception(_moduleLogger)
81         def _on_new_channel(self, bus, serviceName, connObjectPath, channelObjectPath, channelType):
82                 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
83                         return
84
85                 conn = telepathy.client.Connection(serviceName, connObjectPath)
86                 try:
87                         chan = telepathy.client.Channel(serviceName, channelObjectPath)
88                 except dbus.exceptions.UnknownMethodException:
89                         _moduleLogger.exception("Client might not have implemented a deprecated method")
90                         return
91                 missDetection = telepathy_utils.WasMissedCall(
92                         bus, conn, chan, self._on_missed_call, self._on_error_for_missed
93                 )
94                 self._outstandingRequests.append(missDetection)
95
96         @misc_utils.log_exception(_moduleLogger)
97         def _on_missed_call(self, missDetection):
98                 _moduleLogger.info("Missed a call")
99                 self.callMissed.emit()
100                 self._outstandingRequests.remove(missDetection)
101
102         @misc_utils.log_exception(_moduleLogger)
103         def _on_error_for_missed(self, missDetection, reason):
104                 _moduleLogger.debug("Error: %r claims %r" % (missDetection, reason))
105                 self._outstandingRequests.remove(missDetection)
106
107
108 class _DummyMissedCallWatcher(QtCore.QObject):
109
110         callMissed = QtCore.pyqtSignal()
111
112         def __init__(self):
113                 QtCore.QObject.__init__(self)
114                 self._isStarted = False
115
116         @property
117         def isSupported(self):
118                 return False
119
120         @property
121         def isStarted(self):
122                 return self._isStarted
123
124         def start(self):
125                 self._isStarted = True
126
127         def stop(self):
128                 if not self._isStarted:
129                         _moduleLogger.info("voicemail monitor stopped without starting")
130                         return
131                 _moduleLogger.info("Stopping voicemail refresh")
132                 self._isStarted = False
133
134
135 if telepathy is not None:
136         MissedCallWatcher = _MissedCallWatcher
137 else:
138         MissedCallWatcher = _DummyMissedCallWatcher
139
140
141 if __name__ == "__main__":
142         pass
143