From e106dccb475ee09da94d8ffe3ae1ad122f6ee994 Mon Sep 17 00:00:00 2001 From: Krzysztof Klinikowski Date: Sun, 11 Apr 2010 22:40:55 +0200 Subject: Many fixes and modifications. Capabilities implemented, better channel naming. Im not sure is that stable, need more testing. --- sunshine/capabilities.py | 37 +++++++++-- sunshine/channel/contact_list.py | 7 +- sunshine/channel/group.py | 4 +- sunshine/channel/text.py | 4 +- sunshine/channel_manager.py | 140 ++++++++++++++++++++++++++++++++++----- sunshine/connection.py | 11 ++- 6 files changed, 172 insertions(+), 31 deletions(-) (limited to 'sunshine') diff --git a/sunshine/capabilities.py b/sunshine/capabilities.py index d5276cd..0424b74 100644 --- a/sunshine/capabilities.py +++ b/sunshine/capabilities.py @@ -153,7 +153,7 @@ class SunshineCapabilities(telepathy.server.ConnectionInterfaceCapabilities, cc_ret = dbus.Dictionary({}, signature='ua(a{sv}as)') for handle in contacts_handles: ctype = telepathy.CHANNEL_TYPE_TEXT - if handle in self._caps: + if handle in self._caps and ctype in self._caps[handle]: old_gen, old_spec = self._caps[handle][ctype] else: old_gen = 0 @@ -171,6 +171,30 @@ class SunshineCapabilities(telepathy.server.ConnectionInterfaceCapabilities, self.CapabilitiesChanged(ret) self.ContactCapabilitiesChanged(cc_ret) +# def add_create_capability(self, contact_handle): +# """Add the create capability for self handle.""" +# ret = [] +# cc_ret = dbus.Dictionary({}, signature='ua(a{sv}as)') +# +# ctype = telepathy.CHANNEL_TYPE_TEXT +# if handle in self._caps: +# old_gen, old_spec = self._caps[handle][ctype] +# else: +# old_gen = 0 +# old_spec = 0 +# new_gen = old_gen +# new_gen |= telepathy.CONNECTION_CAPABILITY_FLAG_CREATE +# +# diff = (int(handle), ctype, old_gen, new_gen, old_spec, old_spec) +# ret.append(diff) +# +# # ContactCapabilities +# self._contact_caps.setdefault(handle, []).append(self.text_chat_class) +# cc_ret[handle] = self._contact_caps[handle] +# +# self.CapabilitiesChanged(ret) +# self.ContactCapabilitiesChanged(cc_ret) + def _update_capabilities(self, contact): handle = SunshineHandleFactory(self, 'contact', contact.account, contact.network_id) @@ -234,12 +258,17 @@ class SunshineCapabilities(telepathy.server.ConnectionInterfaceCapabilities, contacts list.""" handles = set([self._self_handle]) for contact in self.profile.contacts: - handle = SunshineHandleFactory(self, 'contact', - str(contact), None) - handles.add(handle) + handle = SunshineHandleFactory(self, 'contact', + str(contact.uin), None) + handles.add(handle) self.add_text_capabilities(handles) # These caps were updated before we were online. for caps in self._update_capabilities_calls: self.UpdateCapabilities(caps) self._update_capabilities_calls = [] + + def updateCapabilitiesCalls(self): + # These caps were updated before we were online. + for caps in self._update_capabilities_calls: + self.UpdateCapabilities(caps) diff --git a/sunshine/channel/contact_list.py b/sunshine/channel/contact_list.py index 63bcaa4..e942a03 100644 --- a/sunshine/channel/contact_list.py +++ b/sunshine/channel/contact_list.py @@ -124,9 +124,9 @@ class SunshineListChannel( telepathy.server.ChannelInterfaceGroup): "Abstract Contact List channels" - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): self._conn_ref = weakref.ref(connection) - telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props) + telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props, object_path=None) telepathy.server.ChannelInterfaceGroup.__init__(self) self._populate(connection) @@ -184,6 +184,9 @@ class SunshineListChannel( if ad: added.add(handle) if lp: local_pending.add(handle) if rp: remote_pending.add(handle) + #self._conn_ref()._populate_capabilities() + #capabilities for self handle + self._conn_ref().contactAdded(self._conn_ref().GetSelfHandle()) self.MembersChanged('', added, (), local_pending, remote_pending, 0, telepathy.CHANNEL_GROUP_CHANGE_REASON_NONE) diff --git a/sunshine/channel/group.py b/sunshine/channel/group.py index 6094092..375d07a 100644 --- a/sunshine/channel/group.py +++ b/sunshine/channel/group.py @@ -37,12 +37,12 @@ logger = logging.getLogger('Sunshine.GroupChannel') class SunshineGroupChannel(SunshineListChannel): - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): self.__pending_add = [] self.__pending_remove = [] self.conn = connection self.groups = {} - SunshineListChannel.__init__(self, connection, manager, props) + SunshineListChannel.__init__(self, connection, manager, props, object_path=object_path) self.GroupFlagsChanged(telepathy.CHANNEL_GROUP_FLAG_CAN_ADD | telepathy.CHANNEL_GROUP_FLAG_CAN_REMOVE, 0) @async diff --git a/sunshine/channel/text.py b/sunshine/channel/text.py index 34c2269..9d01f74 100644 --- a/sunshine/channel/text.py +++ b/sunshine/channel/text.py @@ -34,14 +34,14 @@ logger = logging.getLogger('Sunshine.TextChannel') class SunshineTextChannel(telepathy.server.ChannelTypeText): - def __init__(self, conn, manager, conversation, props): + def __init__(self, conn, manager, conversation, props, object_path=None): _, surpress_handler, handle = manager._get_type_requested_handle(props) self._recv_id = 0 self._conn_ref = weakref.ref(conn) self.conn = conn self.handle = handle - telepathy.server.ChannelTypeText.__init__(self, conn, manager, props) + telepathy.server.ChannelTypeText.__init__(self, conn, manager, props, object_path=None) def Send(self, message_type, text): if message_type == telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL: diff --git a/sunshine/channel_manager.py b/sunshine/channel_manager.py index cd02197..f067b6c 100644 --- a/sunshine/channel_manager.py +++ b/sunshine/channel_manager.py @@ -19,6 +19,7 @@ import logging import weakref +from string import ascii_letters, digits import dbus import telepathy @@ -29,57 +30,160 @@ from sunshine.channel.text import SunshineTextChannel, SunshineRoomTextChannel #from sunshine.channel.media import SunshineMediaChannel from sunshine.handle import SunshineHandleFactory +#from butterfly.Channel_Interface_Conference import CHANNEL_INTERFACE_CONFERENCE + __all__ = ['SunshineChannelManager'] logger = logging.getLogger('Sunshine.ChannelManager') +_ASCII_ALNUM = ascii_letters + digits + +# copy/pasted from tp-glib's libtpcodegen +def escape_as_identifier(identifier): + """Escape the given string to be a valid D-Bus object path or service + name component, using a reversible encoding to ensure uniqueness. + + The reversible encoding is as follows: + + * The empty string becomes '_' + * Otherwise, each non-alphanumeric character is replaced by '_' plus + two lower-case hex digits; the same replacement is carried out on + the first character, if it's a digit + """ + # '' -> '_' + if not identifier: + return '_' + + # A bit of a fast path for strings which are already OK. + # We deliberately omit '_' because, for reversibility, that must also + # be escaped. + if (identifier.strip(_ASCII_ALNUM) == '' and + identifier[0] in ascii_letters): + return identifier + + # The first character may not be a digit + if identifier[0] not in ascii_letters: + ret = ['_%02x' % ord(identifier[0])] + else: + ret = [identifier[0]] + + # Subsequent characters may be digits or ASCII letters + for c in identifier[1:]: + if c in _ASCII_ALNUM: + ret.append(c) + else: + ret.append('_%02x' % ord(c)) + + return ''.join(ret) + class SunshineChannelManager(telepathy.server.ChannelManager): + __text_channel_id = 1 + __media_channel_id = 1 + def __init__(self, connection): telepathy.server.ChannelManager.__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_TEXT, - telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_ROOM)} - 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, []) + classes = [ + ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)}, + [telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID']), + + ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_ROOM)}, +# [ +# CHANNEL_INTERFACE_CONFERENCE + '.InitialChannels', +# CHANNEL_INTERFACE_CONFERENCE + '.InitialInviteeHandles', +# CHANNEL_INTERFACE_CONFERENCE + '.InitialInviteeIDs', +# CHANNEL_INTERFACE_CONFERENCE + '.InitialMessage', +# CHANNEL_INTERFACE_CONFERENCE + '.SupportsNonMerges'] + [telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID']), + ] + self.implement_channel_classes(telepathy.CHANNEL_TYPE_TEXT, self._get_text_channel, classes) + + classes = [ + ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_GROUP)}, + [telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID']), + + ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_LIST)}, + [telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID']) + ] + self.implement_channel_classes(telepathy.CHANNEL_TYPE_CONTACT_LIST, self._get_list_channel, classes) + +# classes = [ +# ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA, +# telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)}, +# [telepathy.CHANNEL_INTERFACE + '.TargetHandle', +# telepathy.CHANNEL_INTERFACE + '.TargetID', +# telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio', +# telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo']) +# ] +# self.implement_channel_classes(telepathy.CHANNEL_TYPE_STREAMED_MEDIA, self._get_media_channel, classes) +# +# 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_TEXT, +# telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_ROOM)} +# 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, handle = self._get_type_requested_handle(props) + logger.debug('New contact list channel') + if handle.get_type() == telepathy.HANDLE_TYPE_GROUP: - channel = SunshineGroupChannel(self._conn, self, props) - logger.debug('New group channel') + path = "RosterChannel/Group/%s" % escape_as_identifier(handle.get_name()) + channel = SunshineGroupChannel(self._conn, self, props, object_path=path) else: channel = SunshineContactListChannelFactory(self._conn, self, handle, props) - logger.debug('New contact list channel: %s' % (handle.name)) return channel + +# def _get_list_channel(self, props): +# _, surpress_handler, handle = self._get_type_requested_handle(props) +# +# if handle.get_type() == telepathy.HANDLE_TYPE_GROUP: +# channel = SunshineGroupChannel(self._conn, self, props) +# logger.debug('New group channel') +# else: +# channel = SunshineContactListChannelFactory(self._conn, +# self, handle, props) +# logger.debug('New contact list channel: %s' % (handle.name)) +# return channel def _get_text_channel(self, props, conversation=None): _, surpress_handler, handle = self._get_type_requested_handle(props) + path = "TextChannel%d" % self.__text_channel_id + self.__text_channel_id += 1 + if handle.get_type() == telepathy.HANDLE_TYPE_CONTACT: logger.debug('New text channel for contact handle, name: %s, id: %s, type: %s' % (handle.name, handle.id, handle.type)) - channel = SunshineTextChannel(self._conn, self, conversation, props) + channel = SunshineTextChannel(self._conn, self, conversation, props, object_path=path) return channel elif handle.get_type() == telepathy.HANDLE_TYPE_ROOM: logger.debug('New text channel for room handle, name: %s, id: %s, type: %s' % (handle.name, handle.id, handle.type)) - channel = SunshineRoomTextChannel(self._conn, self, conversation, props) + channel = SunshineRoomTextChannel(self._conn, self, conversation, props, object_path=path) return channel else: raise telepathy.NotImplemented('Unknown handle for text channel.') diff --git a/sunshine/connection.py b/sunshine/connection.py index cbfbd4c..87bda75 100644 --- a/sunshine/connection.py +++ b/sunshine/connection.py @@ -288,6 +288,9 @@ class SunshineConnection(telepathy.server.Connection, SunshinePresence.__init__(self) SunshineAvatars.__init__(self) SunshineContacts.__init__(self) + SunshineCapabilities.__init__(self) + + self.updateCapabilitiesCalls() self.set_self_handle(SunshineHandleFactory(self, 'self')) @@ -361,6 +364,9 @@ class SunshineConnection(telepathy.server.Connection, #if reactor.running: # reactor.stop() + def GetInterfaces(self): + return self._interfaces + def RequestHandles(self, handle_type, names, sender): logger.info("Method RequestHandles called, handle type: %s, names: %s" % (str(handle_type), str(names))) self.check_connected() @@ -503,7 +509,6 @@ class SunshineConnection(telepathy.server.Connection, self.makeTelepathyGroupChannels() SunshineAliasing.__init__(self) - SunshineCapabilities.__init__(self) self._status = telepathy.CONNECTION_STATUS_CONNECTED self.StatusChanged(telepathy.CONNECTION_STATUS_CONNECTED, @@ -528,12 +533,12 @@ class SunshineConnection(telepathy.server.Connection, self.makeTelepathyGroupChannels() SunshineAliasing.__init__(self) - SunshineCapabilities.__init__(self) self._status = telepathy.CONNECTION_STATUS_CONNECTED self.StatusChanged(telepathy.CONNECTION_STATUS_CONNECTED, telepathy.CONNECTION_STATUS_REASON_REQUESTED) - self._populate_capabilities() + #self._populate_capabilities() + #self.contactAdded(self.GetSelfHandle()) def on_loginFailed(self, response): logger.info("Login failed: ", response) -- cgit v1.2.3