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 self._connRef().session.voicemails.updateSignalHandler.unregister_sink(
45 self._connRef().session.texts.updateSignalHandler.unregister_sink(
48 self.__callback = None
50 @gtk_toolbox.log_exception(_moduleLogger)
51 def _on_conversations_updated(self, conv, conversationIds):
52 _moduleLogger.debug("Incoming messages from: %r" % (conversationIds, ))
53 for phoneNumber in conversationIds:
54 h = self._connRef().get_handle_by_name(telepathy.HANDLE_TYPE_CONTACT, phoneNumber)
55 # Just let the TextChannel decide whether it should be reported to the user or not
56 props = self._connRef().generate_props(telepathy.CHANNEL_TYPE_TEXT, h, False)
57 if self._connRef()._channel_manager.channel_exists(props):
60 # Maemo 4.1's RTComm opens a window for a chat regardless if a
61 # message is received or not, so we need to do some filtering here
62 mergedConv = conv.get_conversation(phoneNumber)
65 for conversation in mergedConv.conversations
66 if not conversation.isRead and not conversation.isArchived
71 chan = self._connRef()._channel_manager.channel_for_props(props, signal=True)
74 class RefreshVoicemail(object):
76 def __init__(self, connRef):
77 self._connRef = connRef
78 self._newChannelSignaller = telepathy_utils.NewChannelSignaller(self._on_new_channel)
79 self._outstandingRequests = []
82 self._newChannelSignaller.start()
85 _moduleLogger.info("Stopping voicemail refresh")
86 self._newChannelSignaller.stop()
88 # I don't want to trust whether the cancel happens within the current
89 # callback or not which could be the deciding factor between invalid
90 # iterators or infinite loops
91 localRequests = [r for r in self._outstandingRequests]
92 for request in localRequests:
93 localRequests.cancel()
95 @gtk_toolbox.log_exception(_moduleLogger)
96 def _on_new_channel(self, bus, serviceName, connObjectPath, channelObjectPath, channelType):
97 if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
100 cmName = telepathy_utils.cm_from_path(connObjectPath)
101 if cmName == constants._telepathy_implementation_name_:
102 _moduleLogger.debug("Ignoring channels from self to prevent deadlock")
105 conn = telepathy.client.Connection(serviceName, connObjectPath)
106 chan = telepathy.client.Channel(serviceName, channelObjectPath)
107 missDetection = telepathy_utils.WasMissedCall(
108 bus, conn, chan, self._on_missed_call, self._on_error_for_missed
110 self._outstandingRequests.append(missDetection)
112 @gtk_toolbox.log_exception(_moduleLogger)
113 def _on_missed_call(self, missDetection):
114 _moduleLogger.info("Missed a call")
115 self._connRef().session.voicemailsStateMachine.reset_timers()
116 self._outstandingRequests.remove(missDetection)
118 @gtk_toolbox.log_exception(_moduleLogger)
119 def _on_error_for_missed(self, missDetection, reason):
120 _moduleLogger.debug("Error: %r claims %r" % (missDetection, reason))
121 self._outstandingRequests.remove(missDetection)
124 class AutoDisconnect(object):
126 def __init__(self, connRef):
127 self._connRef = connRef
128 if conic is not None:
129 self.__connection = conic.Connection()
131 self.__connection = None
133 self.__connectionEventId = None
134 self.__delayedDisconnectEventId = None
137 if self.__connection is not None:
138 self.__connectionEventId = self.__connection.connect("connection-event", self._on_connection_change)
141 self._cancel_delayed_disconnect()
143 @gtk_toolbox.log_exception(_moduleLogger)
144 def _on_connection_change(self, connection, event):
148 status = event.get_status()
149 error = event.get_error()
150 iap_id = event.get_iap_id()
151 bearer = event.get_bearer_type()
153 if status == conic.STATUS_DISCONNECTED:
154 _moduleLogger.info("Disconnected from network, starting countdown to logoff")
155 self.__delayedDisconnectEventId = gobject_utils.timeout_add_seconds(
156 5, self._on_delayed_disconnect
158 elif status == conic.STATUS_CONNECTED:
159 _moduleLogger.info("Connected to network")
160 self._cancel_delayed_disconnect()
162 _moduleLogger.info("Other status: %r" % (status, ))
164 def _cancel_delayed_disconnect(self):
165 if self.__delayedDisconnectEventId is None:
167 _moduleLogger.info("Cancelling auto-log off")
168 gobject.source_reove(self.__delayedDisconnectEventId)
169 self.__delayedDisconnectEventId = None
171 @gtk_toolbox.log_exception(_moduleLogger)
172 def _on_delayed_disconnect(self):
173 if not self.session.is_logged_in():
174 _moduleLogger.info("Received connection change event when not logged in")
176 self._connRef().StatusChanged(
177 telepathy.CONNECTION_STATUS_DISCONNECTED,
178 telepathy.CONNECTION_STATUS_REASON_NETWORK_ERROR
181 self._connRef().disconnect()
183 _moduleLogger.exception("Error durring disconnect")
184 self.__delayedDisconnectEventId = None