Added detection of missed calls. As part of this I moved some of the connections...
[theonering] / src / util / tp_utils.py
old mode 100755 (executable)
new mode 100644 (file)
index 3371679..dbf06ec
 #!/usr/bin/env python
 
-import sys
-sys.path.insert(0,"../src")
 import logging
-import pprint
 
 import gobject
 import dbus
-import dbus.mainloop.glib
 import telepathy
 
 import util.go_utils as gobject_utils
 import gtk_toolbox
 
 
-_moduleLogger = logging.getLogger("receptionist")
+_moduleLogger = logging.getLogger("tp_utils")
 DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
 
 
-class AutoAcceptCall(object):
-
-       def __init__(self, bus, conn, chan, on_success, on_error):
-               self._sessionBus = bus
-               self._conn = conn
-               self._chan = chan
-               self._outstandingRequests = []
-               self._on_success = on_success
-               self._on_error = on_error
-
-               self._initiatorHandle = None
-               self._initiatorID = None
-               self._targetHandle = None
-               self._targetID = None
-               self._requested = None
-               self._pendingHandles = None
-
-               self._chan[DBUS_PROPERTIES].GetAll(
-                       telepathy.interfaces.CHANNEL_INTERFACE,
-                       reply_handler = self._on_got_all,
-                       error_handler = self._custom_error(self._on_got_all),
-               )
-               self._outstandingRequests.append(self._on_got_all)
-
-               if False:
-                       # @bug Unsure why this isn't working
-                       self._chan[DBUS_PROPERTIES].Get(
-                               telepathy.interfaces.CHANNEL_INTERFACE_GROUP,
-                               'LocalPendingMembers',
-                               reply_handler = self._on_got_pending_members,
-                               error_handler = self._custom_error(self._on_got_pending_members),
-                       )
-               else:
-                       self._chan[telepathy.interfaces.CHANNEL_INTERFACE_GROUP].GetLocalPendingMembersWithInfo(
-                               reply_handler = self._on_got_pending_members,
-                               error_handler = self._custom_error(self._on_got_pending_members),
-                       )
-               self._outstandingRequests.append(self._on_got_pending_members)
-
-       def is_inbound(self):
-               return not self._requested
-               isInbound = self._targetHandle == self._initiatorHandle
-               return isInbound
-
-       @property
-       def initiator(self):
-               return self._initiatorID
-
-       @property
-       def target(self):
-               return self._targetID
-
-       def accept_call(self, on_accepted, on_error):
-               self._chan[telepathy.interfaces.CHANNEL_INTERFACE_GROUP].AddMembers(
-                       self._pendingHandles,
-                       "",
-                       reply_handler = self._custom_on_accept(on_accepted),
-                       error_handler = self._custom_on_accept_error(on_error),
-               )
-
-       def _custom_on_accept(self, callback):
-
-               def on_accept(*args):
-                       callback(self)
-
-               return on_accept
-
-       def _custom_on_accept_error(self, callback):
-
-               def on_error(*args):
-                       callback(self, *args)
-
-               return on_error
-
-       def _custom_error(self, action):
-
-               def _on_error(*args):
-                       _moduleLogger.error("Failed for %r (%r)" % (action, args))
-                       self._outstandingRequests.remove(action)
-                       if self._outstandingRequests:
-                               return
-
-                       self._on_error(self)
-
-               return _on_error
-
-       def _report_callback_done(self, action):
-               _moduleLogger.debug("Succeded with %r" % (action, ))
-               self._outstandingRequests.remove(action)
-               if self._outstandingRequests:
-                       return
-
-               assert None not in (
-                       self._initiatorHandle,
-                       self._initiatorID,
-                       self._targetHandle,
-                       self._targetID,
-                       self._pendingHandles,
-                       self._requested,
-               )
-
-               self._on_success(self)
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_got_all(self, properties):
-               self._initiatorID = properties["InitiatorID"]
-               self._initiatorHandle = properties["InitiatorHandle"]
-               self._targetID = properties["InitiatorID"]
-               self._targetHandle = properties["InitiatorHandle"]
-               self._requested = properties["Requested"]
-
-               self._report_callback_done(self._on_got_all)
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_got_pending_members(self, pendings):
-               for pendingHandle, instigatorHandle, reason, message in pendings:
-                       print pendingHandle, instigatorHandle, reason, message
-
-               self._pendingHandles = [pendingWithInfo[0] for pendingWithInfo in pendings]
-
-               self._report_callback_done(self._on_got_pending_members)
-
-
 class WasMissedCall(object):
 
        def __init__(self, bus, conn, chan, on_success, on_error):
@@ -210,7 +83,6 @@ class WasMissedCall(object):
 
        @gtk_toolbox.log_exception(_moduleLogger)
        def _on_members_changed(self, message, added, removed, lp, rp, actor, reason):
-               pprint.pprint((message, added, removed, lp, rp, actor, reason))
                if added:
                        self._didMembersChange = True
                        self._report_missed_if_ready()
@@ -258,91 +130,32 @@ class NewChannelSignaller(object):
        def _on_new_channel(
                self, channelObjectPath, channelType, handleType, handle, supressHandler
        ):
-               connObjectPath = channelObjectPath.rsplit("/", 1)[0]
-               serviceName = connObjectPath[1:].replace("/", ".")
-               conn = telepathy.client.Connection(serviceName, connObjectPath)
-               chan = telepathy.client.Channel(serviceName, channelObjectPath)
-               self._on_user_new_channel(self._sessionBus, conn, chan, channelType)
-
-
-class AutoAcceptManager(object):
-
-       def __init__(self):
-               self._newChannelSignaller = NewChannelSignaller(self._on_new_channel)
-
-       def start(self):
-               self._newChannelSignaller.start()
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_new_channel(self, bus, conn, chan, channelType):
-               pprint.pprint((bus, conn, chan, channelType))
-               if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
-                       return
-
-               # @todo distinguish between preferred CMs
-               attemptPickup = AutoAcceptCall(bus, conn, chan, self._on_inbound_call, self._on_inbound_call_error)
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_inbound_call(self, autoAcceptCall):
-               # @todo Add a comparison for picking up for only certain contacts
-               print autoAcceptCall.initiator, autoAcceptCall.target
-               if autoAcceptCall.is_inbound():
-                       autoAcceptCall.accept_call(self._on_call_pickedup, self._on_pickup_error)
-               else:
-                       _moduleLogger.debug(
-                               "Not an inbound call (initiator=%r, target=%r)" % (autoAcceptCall.initiator, autoAcceptCall.target)
-                       )
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_inbound_call_error(self, *args):
-               _moduleLogger.info("Inbound call error")
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_call_pickedup(self, autoAcceptCall):
-               _moduleLogger.info("Call picked up")
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_pickup_error(self, autoAcceptCall, *args):
-               _moduleLogger.info("Call failed to pick up (%r)" % (args, ))
-
-
-class MissedManager(object):
-
-       def __init__(self):
-               self._newChannelSignaller = NewChannelSignaller(self._on_new_channel)
-
-       def start(self):
-               self._newChannelSignaller.start()
-
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_new_channel(self, bus, conn, chan, channelType):
-               pprint.pprint((bus, conn, chan, channelType))
-               if channelType != telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA:
-                       return
-
-               missDetection = WasMissedCall(
-                       bus, conn, chan, self._on_missed_call, self._on_error_for_missed
+               connObjectPath = channel_path_to_conn_path(channelObjectPath)
+               serviceName = path_to_service_name(channelObjectPath)
+               self._on_user_new_channel(
+                       self._sessionBus, serviceName, connObjectPath, channelObjectPath, channelType
                )
 
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_missed_call(self, missDetection):
-               _moduleLogger.info("Missed a call")
 
-       @gtk_toolbox.log_exception(_moduleLogger)
-       def _on_error_for_missed(self, missDetection, reason):
-               _moduleLogger.info("Error: %r claims %r" % (missDetection, reason))
+def channel_path_to_conn_path(channelObjectPath):
+       """
+       >>> channel_path_to_conn_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/sip/USERNAME/Channel1")
+       '/org/freedesktop/Telepathy/ConnectionManager/theonering/sip/USERNAME'
+       """
+       return channelObjectPath.rsplit("/", 1)[0]
 
 
-if __name__ == "__main__":
-       logging.basicConfig(level=logging.DEBUG)
-       l = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-       if False:
-               manager = AutoAcceptManager()
-       else:
-               manager = MissedManager()
+def path_to_service_name(path):
+       """
+       >>> path_to_service_name("/org/freedesktop/Telepathy/ConnectionManager/theonering/sip/USERNAME/Channel1")
+       'org.freedesktop.Telepathy.ConnectionManager.theonering.sip.USERNAME'
+       """
+       return ".".join(path[1:].split("/")[0:7])
 
-       gobject.threads_init()
-       gobject.idle_add(manager.start)
 
-       mainloop = gobject.MainLoop(is_running=True)
-       mainloop.run()
+def cm_from_path(path):
+       """
+       >>> cm_from_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/sip/USERNAME/Channel1")
+       'theonering'
+       """
+       return path[1:].split("/")[4]