-import weakref
import logging
+import dbus
import telepathy
import channel
+import util.misc as util_misc
-class ChannelManager(object):
+_moduleLogger = logging.getLogger("channel_manager")
+
+
+class TelepathyChannelManager(object):
def __init__(self, connection):
- self._connRef = weakref.ref(connection)
- self._listChannels = weakref.WeakValueDictionary()
- self._textChannels = weakref.WeakValueDictionary()
+ self._conn = connection
+
+ self._requestable_channel_classes = dict()
+ self._channels = dict()
+ self._fixed_properties = dict()
+ self._available_properties = dict()
def close(self):
- for chan in self._listChannels.values():
- chan.remove_from_connection()# so that dbus lets it die.
- for chan in self._textChannels.values():
- chan.Close()
-
- def channel_for_list(self, handle, suppress_handler=False):
- if handle in self._listChannels:
- chan = self._listChannels[handle]
+ for channel_type in self._requestable_channel_classes:
+ for chan in self._channels[channel_type].values():
+ try:
+ _moduleLogger.debug("Closing %s %s" % (channel_type, chan._object_path))
+ chan.Close()
+ except Exception:
+ _moduleLogger.exception("Shutting down %r" % (chan, ))
+
+ def remove_channel(self, chan):
+ for channel_type in self._requestable_channel_classes:
+ for handle, ichan in self._channels[channel_type].items():
+ if chan == ichan:
+ del self._channels[channel_type][handle]
+
+ def _get_type_requested_handle(self, props):
+ type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType']
+ requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
+ target_handle = props[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle']
+ target_handle_type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType']
+
+ handle = self._conn._handles[target_handle_type, target_handle]
+
+ return (type, requested, handle)
+
+ def channel_exists(self, props):
+ type, _, handle = self._get_type_requested_handle(props)
+
+ if type in self._channels:
+ if handle in self._channels[type]:
+ return True
+
+ return False
+
+ def channel_for_props(self, props, signal=True, **args):
+ type, suppress_handler, handle = self._get_type_requested_handle(props)
+
+ if type not in self._requestable_channel_classes:
+ raise NotImplemented('Unknown channel type "%s"' % type)
+
+ if self.channel_exists(props):
+ return self._channels[type][handle]
+
+ chan = self._requestable_channel_classes[type](props, **args)
+
+ if hasattr(self._conn, "add_channels"):
+ # HACK Newer python-telepathy
+ self._conn.add_channels([chan], signal=signal)
+ elif hasattr(self._conn, "add_channel"):
+ # HACK Older python-telepathy
+ self._conn.NewChannels([(chan._object_path, chan.get_props())])
+ self._conn.add_channel(chan, handle, suppress_handler)
else:
- if handle.get_type() == telepathy.HANDLE_TYPE_GROUP:
- chan = channel.group.GroupChannel(self._connRef(), handle)
- elif handle.get_type() == telepathy.HANDLE_TYPE_CONTACT:
- chan = channel.contact_list.creat_contact_list_channel(self._connRef(), handle)
- else:
- logging.warn("Unknown channel type %r" % handle.get_type())
- self._listChannels[handle] = chan
- self._connRef().add_channel(chan, handle, suppress_handler)
+ raise RuntimeError("Uhh, what just happened with the connection")
+ self._channels[type][handle] = chan
+
return chan
- def channel_for_text(self, handle, conversation=None, suppress_handler=False):
- if handle in self._textChannels:
- chan = self._textChannels[handle]
+ def _implement_channel_class(self, type, make_channel, fixed, available):
+ self._requestable_channel_classes[type] = make_channel
+ self._channels.setdefault(type, {})
+
+ self._fixed_properties[type] = fixed
+ self._available_properties[type] = available
+
+ def get_requestable_channel_classes(self):
+ retval = []
+
+ for channel_type in self._requestable_channel_classes:
+ retval.append((self._fixed_properties[channel_type],
+ self._available_properties[channel_type]))
+
+ return retval
+
+
+class ChannelManager(TelepathyChannelManager):
+
+ def __init__(self, connection):
+ TelepathyChannelManager.__init__(self, connection)
+
+ fixed = {
+ telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT,
+ telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
+ }
+ self._implement_channel_class(
+ telepathy.CHANNEL_TYPE_TEXT,
+ self._get_text_channel,
+ fixed,
+ []
+ )
+
+ fixed = {
+ telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST
+ }
+ self._implement_channel_class(
+ telepathy.CHANNEL_TYPE_CONTACT_LIST,
+ self._get_list_channel,
+ fixed,
+ []
+ )
+
+ fixed = {
+ telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
+ telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
+ }
+ self._implement_channel_class(
+ telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
+ self._get_media_channel,
+ fixed,
+ [telepathy.CHANNEL_INTERFACE + '.TargetHandle']
+ )
+
+ def _get_list_channel(self, props):
+ _, surpress_handler, h = self._get_type_requested_handle(props)
+
+ _moduleLogger.debug('New contact list channel')
+ chan = channel.contact_list.create_contact_list_channel(self._conn, self, props, h)
+ return chan
+
+ def _get_text_channel(self, props):
+ _, surpress_handler, h = self._get_type_requested_handle(props)
+
+ accountNumber = util_misc.strip_number(self._conn.session.backend.get_account_number())
+ if h.phoneNumber == accountNumber:
+ _moduleLogger.debug('New Debug channel')
+ chan = channel.debug_prompt.DebugPromptChannel(self._conn, self, props, h)
else:
- logging.debug("Requesting new text channel")
- contact = handle.contact
-
- if conversation is None:
- client = self._connRef().msn_client
- conversation = None
- chan = channel.text.TextChannel(self._connRef(), conversation)
- self._textChannels[handle] = chan
- self._connRef().add_channel(chan, handle, suppress_handler)
+ _moduleLogger.debug('New text channel')
+ chan = channel.text.TextChannel(self._conn, self, props, h)
+ return chan
+
+ def _get_media_channel(self, props):
+ _, surpress_handler, h = self._get_type_requested_handle(props)
+
+ _moduleLogger.debug('New media channel')
+ chan = channel.call.CallChannel(self._conn, self, props, h)
return chan