9 except (ImportError, OSError):
13 import util.coroutines as coroutines
14 import util.go_utils as gobject_utils
15 import util.tp_utils as telepathy_utils
19 _moduleLogger = logging.getLogger("autogv")
22 class NewGVConversations(object):
24 def __init__(self, connRef):
25 self._connRef = connRef
26 self.__callback = None
29 self.__callback = coroutines.func_sink(
30 coroutines.expand_positional(
31 self._on_conversations_updated
34 self._connRef().session.voicemails.updateSignalHandler.register_sink(
37 self._connRef().session.texts.updateSignalHandler.register_sink(
42 if self.__callback is None:
43 _moduleLogger.info("New conversation monitor stopped without starting")
45 self._connRef().session.voicemails.updateSignalHandler.unregister_sink(
48 self._connRef().session.texts.updateSignalHandler.unregister_sink(
51 self.__callback = None
53 @gtk_toolbox.log_exception(_moduleLogger)
54 def _on_conversations_updated(self, conv, conversationIds):
55 _moduleLogger.debug("Incoming messages from: %r" % (conversationIds, ))
56 for phoneNumber in conversationIds:
57 h = self._connRef().get_handle_by_name(telepathy.HANDLE_TYPE_CONTACT, phoneNumber)
58 # Just let the TextChannel decide whether it should be reported to the user or not
59 props = self._connRef().generate_props(telepathy.CHANNEL_TYPE_TEXT, h, False)
60 if self._connRef()._channel_manager.channel_exists(props):
63 # Maemo 4.1's RTComm opens a window for a chat regardless if a
64 # message is received or not, so we need to do some filtering here
65 mergedConv = conv.get_conversation(phoneNumber)
68 for conversation in mergedConv.conversations
69 if not conversation.isRead and not conversation.isArchived
74 chan = self._connRef()._channel_manager.channel_for_props(props, signal=True)
77 class RefreshVoicemail(object):
79 def __init__(self, connRef):
80 self._connRef = connRef
81 self._newChannelSignaller = telepathy_utils.NewChannelSignaller(self._on_new_channel)
82 self._outstandingRequests = []
83 self._isStarted = False
86 self._newChannelSignaller.start()
87 self._isStarted = True
90 if not self._isStarted:
91 _moduleLogger.info("voicemail monitor stopped without starting")
93 _moduleLogger.info("Stopping voicemail refresh")
94 self._newChannelSignaller.stop()
96 # I don't want to trust whether the cancel happens within the current
97 # callback or not which could be the deciding factor between invalid
98 # iterators or infinite loops
99 localRequests = [r for r in self._outstandingRequests]
100 for request in localRequests:
101 localRequests.cancel()
103 self._isStarted = False
105 @gtk_toolbox.log_exception(_moduleLogger)
106 def _on_new_channel(self, bus, serviceName, connObjectPath, channelObjectPath, channelType):
107 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
110 cmName = telepathy_utils.cm_from_path(connObjectPath)
111 if cmName == constants._telepathy_implementation_name_:
112 _moduleLogger.debug("Ignoring channels from self to prevent deadlock")
115 conn = telepathy.client.Connection(serviceName, connObjectPath)
116 chan = telepathy.client.Channel(serviceName, channelObjectPath)
117 missDetection = telepathy_utils.WasMissedCall(
118 bus, conn, chan, self._on_missed_call, self._on_error_for_missed
120 self._outstandingRequests.append(missDetection)
122 @gtk_toolbox.log_exception(_moduleLogger)
123 def _on_missed_call(self, missDetection):
124 _moduleLogger.info("Missed a call")
125 self._connRef().session.voicemailsStateMachine.reset_timers()
126 self._outstandingRequests.remove(missDetection)
128 @gtk_toolbox.log_exception(_moduleLogger)
129 def _on_error_for_missed(self, missDetection, reason):
130 _moduleLogger.debug("Error: %r claims %r" % (missDetection, reason))
131 self._outstandingRequests.remove(missDetection)
134 class AutoDisconnect(object):
136 def __init__(self, connRef):
137 self._connRef = connRef
138 if conic is not None:
139 self.__connection = conic.Connection()
141 self.__connection = None
143 self.__connectionEventId = None
144 self.__delayedDisconnectEventId = None
147 if self.__connection is not None:
148 self.__connectionEventId = self.__connection.connect("connection-event", self._on_connection_change)
151 self._cancel_delayed_disconnect()
153 @gtk_toolbox.log_exception(_moduleLogger)
154 def _on_connection_change(self, connection, event):
158 status = event.get_status()
159 error = event.get_error()
160 iap_id = event.get_iap_id()
161 bearer = event.get_bearer_type()
163 if status == conic.STATUS_DISCONNECTED:
164 _moduleLogger.info("Disconnected from network, starting countdown to logoff")
165 self.__delayedDisconnectEventId = gobject_utils.timeout_add_seconds(
166 5, self._on_delayed_disconnect
168 elif status == conic.STATUS_CONNECTED:
169 _moduleLogger.info("Connected to network")
170 self._cancel_delayed_disconnect()
172 _moduleLogger.info("Other status: %r" % (status, ))
174 def _cancel_delayed_disconnect(self):
175 if self.__delayedDisconnectEventId is None:
177 _moduleLogger.info("Cancelling auto-log off")
178 gobject.source_reove(self.__delayedDisconnectEventId)
179 self.__delayedDisconnectEventId = None
181 @gtk_toolbox.log_exception(_moduleLogger)
182 def _on_delayed_disconnect(self):
183 if not self.session.is_logged_in():
184 _moduleLogger.info("Received connection change event when not logged in")
187 self._connRef().disconnect(telepathy.CONNECTION_STATUS_REASON_NETWORK_ERROR)
189 _moduleLogger.exception("Error durring disconnect")
190 self.__delayedDisconnectEventId = None