def __init__(self, connection):
tp.ChannelManager.__init__(self, connection)
- fixed = {
- telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST
- }
- self._implement_channel_class(
+ classes = [
+ (
+ {
+ 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,
- fixed,
- []
+ classes,
)
- fixed = {
- telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT,
- telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
- }
- self._implement_channel_class(
+ 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',
+ ],
+ ),
+ ]
+ self.implement_channel_classes(
telepathy.CHANNEL_TYPE_TEXT,
self._get_text_channel,
- fixed,
- []
+ classes,
)
- fixed = {
- telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_FILE_TRANSFER,
- telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
- }
- self._implement_channel_class(
+ classes = [
+ (
+ {
+ telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_FILE_TRANSFER,
+ telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
+ },
+ [
+ telepathy.CHANNEL_INTERFACE + '.TargetHandle',
+ telepathy.CHANNEL_INTERFACE + '.TargetID',
+ ],
+ ),
+ ]
+ self.implement_channel_classes(
telepathy.CHANNEL_TYPE_FILE_TRANSFER,
self._get_file_transfer_channel,
- fixed,
- []
+ classes,
)
- fixed = {
- telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
- telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)
- }
- self._implement_channel_class(
+ 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,
- fixed,
- [telepathy.CHANNEL_INTERFACE + '.TargetHandle']
+ classes,
)
def _get_list_channel(self, props):
import dbus.service
from telepathy.constants import (CONNECTION_HANDLE_TYPE_NONE,
- CHANNEL_TEXT_MESSAGE_TYPE_NORMAL)
+ CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
+ HANDLE_TYPE_NONE)
from telepathy.errors import InvalidArgument
from properties import DBusProperties
+from handle import NoneHandle
+
class Channel(_Channel, DBusProperties):
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the base channel object.
"""
self._conn = connection
self._chan_manager = manager
- object_path = self._conn.get_channel_path()
+
+ object_path = self._conn.get_channel_path(object_path)
_Channel.__init__(self, self._conn._name, object_path)
self._type = props[CHANNEL_INTERFACE + '.ChannelType']
self._immutable_properties = dict()
- self._handle = self._conn.get_handle_by_id(
- props[CHANNEL_INTERFACE + '.TargetHandleType'],
- props[CHANNEL_INTERFACE + '.TargetHandle'])
+ tht = props.get(CHANNEL_INTERFACE + '.TargetHandleType', HANDLE_TYPE_NONE)
+
+ if tht == HANDLE_TYPE_NONE:
+ self._handle = NoneHandle()
+ else:
+ self._handle = self._conn.get_handle_by_id(
+ props[CHANNEL_INTERFACE + '.TargetHandleType'],
+ props[CHANNEL_INTERFACE + '.TargetHandle'])
+
self._interfaces = set()
DBusProperties.__init__(self)
{'ChannelType': lambda: dbus.String(self.GetChannelType()),
'Interfaces': lambda: dbus.Array(self.GetInterfaces(), signature='s'),
'TargetHandle': lambda: dbus.UInt32(self._handle.get_id()),
- 'TargetHandleType': lambda: dbus.UInt32(self._get_handle_type()),
- 'TargetID': lambda: dbus.String(self._get_target_id()),
+ 'TargetHandleType': lambda: dbus.UInt32(self._handle.get_type()),
+ 'TargetID': lambda: dbus.String(self._handle.get_name()),
'Requested': lambda: self._requested})
self._add_immutables({
def _add_immutables(self, props):
self._immutable_properties.update(props)
- def _get_handle_type(self):
- if self._handle:
- return self._handle.get_type()
- else:
- return CONNECTION_HANDLE_TYPE_NONE
-
- def _get_target_id(self):
- if self._handle:
- return self._handle.get_name()
- else:
- return ''
-
def get_props(self):
+ """Despite its name, this function actually only returns immutable channel
+ properties."""
props = dict()
for prop, iface in self._immutable_properties.items():
props[iface + '.' + prop] = \
""" Returns the handle type and number if this channel represents a
communication with a particular contact, room or server-stored list, or
zero if it is transient and defined only by its contents. """
- if self._handle:
- return self._handle.get_type(), self._handle
- else:
- return (CONNECTION_HANDLE_TYPE_NONE, 0)
+ return (self._handle.get_type(), self._handle.get_id())
@dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as')
def GetInterfaces(self):
class ChannelTypeContactList(Channel, _ChannelTypeContactListIface):
__doc__ = _ChannelTypeContactListIface.__doc__
- def __init__(self, connection, manager, props):
- """
- Initialise the channel.
-
- Parameters:
- connection - the parent Telepathy Connection object
- """
- Channel.__init__(self, connection, manager, props)
-
-
-from telepathy._generated.Channel_Type_File_Transfer \
- import ChannelTypeFileTransfer as _ChannelTypeFileTransferIface
-
-class ChannelTypeFileTransfer(Channel, _ChannelTypeFileTransferIface):
- __doc__ = _ChannelTypeFileTransferIface.__doc__
-
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the channel.
Parameters:
connection - the parent Telepathy Connection object
"""
- Channel.__init__(self, connection, manager, props)
+ Channel.__init__(self, connection, manager, props,
+ object_path=object_path)
from telepathy._generated.Channel_Type_File_Transfer \
class ChannelTypeFileTransfer(Channel, _ChannelTypeFileTransferIface):
__doc__ = _ChannelTypeFileTransferIface.__doc__
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the channel.
Parameters:
connection - the parent Telepathy Connection object
"""
- Channel.__init__(self, connection, manager, props)
+ Channel.__init__(self, connection, manager, props,
+ object_path=object_path)
from telepathy._generated.Channel_Type_Streamed_Media \
class ChannelTypeStreamedMedia(Channel, _ChannelTypeStreamedMediaIface):
__doc__ = _ChannelTypeStreamedMediaIface.__doc__
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the channel.
Parameters:
connection - the parent Telepathy Connection object
"""
- Channel.__init__(self, connection, manager, props)
+ Channel.__init__(self, connection, manager, props,
+ object_path=object_path)
from telepathy._generated.Channel_Type_Room_List \
class ChannelTypeRoomList(Channel, _ChannelTypeRoomListIface):
__doc__ = _ChannelTypeRoomListIface.__doc__
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the channel.
Parameters:
connection - the parent Telepathy Connection object
"""
- Channel.__init__(self, connection, manager, props)
+ Channel.__init__(self, connection, manager, props,
+ object_path=object_path)
self._listing_rooms = False
self._rooms = {}
- self._add_immutables(self, {'Server': CHANNEL_TYPE_ROOM_LIST})
+ self._add_immutables({'Server': CHANNEL_TYPE_ROOM_LIST})
@dbus.service.method(CHANNEL_TYPE_ROOM_LIST, in_signature='', out_signature='b')
def GetListingRooms(self):
class ChannelTypeText(Channel, _ChannelTypeTextIface):
__doc__ = _ChannelTypeTextIface.__doc__
- def __init__(self, connection, manager, props):
+ def __init__(self, connection, manager, props, object_path=None):
"""
Initialise the channel.
Parameters:
connection - the parent Telepathy Connection object
"""
- Channel.__init__(self, connection, manager, props)
+ Channel.__init__(self, connection, manager, props,
+ object_path=object_path)
self._pending_messages = {}
self._message_types = [CHANNEL_TEXT_MESSAGE_TYPE_NORMAL]
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+import warnings
+
from telepathy.errors import NotImplemented
from telepathy.interfaces import (CHANNEL_INTERFACE,
- CHANNEL_TYPE_CONTACT_LIST)
+ CHANNEL_TYPE_CONTACT_LIST)
+
+from telepathy.constants import HANDLE_TYPE_NONE
+
+from handle import NoneHandle
class ChannelManager(object):
def __init__(self, connection):
self._conn = connection
- self._requestable_channel_classes = dict()
+ self._requestable_channels = dict()
self._channels = dict()
+
self._fixed_properties = dict()
self._available_properties = dict()
+ self._requestables = dict()
+
def close(self):
"""Close channel manager and all the existing channels."""
- for channel_type in self._requestable_channel_classes:
+ for channel_type in self._requestable_channels:
for channels in self._channels[channel_type].values():
for channel in channels:
if channel._type == CHANNEL_TYPE_CONTACT_LIST:
def remove_channel(self, channel):
"Remove channel from the channel manager"
- for channel_type in self._requestable_channel_classes:
+ for channel_type in self._requestable_channels:
for handle, channels in self._channels[channel_type].items():
if channel in channels :
channels.remove(channel)
properties"""
type = props[CHANNEL_INTERFACE + '.ChannelType']
requested = props[CHANNEL_INTERFACE + '.Requested']
- target_handle = int(props[CHANNEL_INTERFACE + '.TargetHandle'])
- target_handle_type = int(props[CHANNEL_INTERFACE + '.TargetHandleType'])
- handle = self._conn._handles[target_handle_type, target_handle]
+ target_handle_type = \
+ props.get(CHANNEL_INTERFACE + '.TargetHandleType', HANDLE_TYPE_NONE)
+
+ if target_handle_type == HANDLE_TYPE_NONE:
+ handle = NoneHandle()
+ else:
+ target_handle = props[CHANNEL_INTERFACE + '.TargetHandle']
+ handle = self._conn._handles[target_handle_type, target_handle]
return (type, requested, handle)
"""Create a new channel with theses properties"""
type, _, handle = self._get_type_requested_handle(props)
- if type not in self._requestable_channel_classes:
+ if type not in self._requestable_channels:
raise NotImplemented('Unknown channel type "%s"' % type)
- channel = self._requestable_channel_classes[type](
+ channel = self._requestable_channels[type](
props, **args)
self._conn.add_channels([channel], signal=signal)
- if type in self._channels:
+ if handle.get_type() != HANDLE_TYPE_NONE and type in self._channels:
self._channels[type].setdefault(handle, []).append(channel)
return channel
else:
return self.create_channel_for_props(props, signal, **args)
+ # Should use implement_channel_classes instead.
def _implement_channel_class(self, type, make_channel, fixed, available):
- """Notify channel manager a channel with these properties can be created"""
- self._requestable_channel_classes[type] = make_channel
+ """Implement channel types in the channel manager, and add one channel
+ class that is retrieved in RequestableChannelClasses.
+
+ self.implement_channel_classes should be used instead, as it allows
+ implementing multiple channel classes."""
+ warnings.warn('deprecated in favour of implement_channel_classes',
+ DeprecationWarning)
+
+ self._requestable_channels[type] = make_channel
self._channels.setdefault(type, {})
self._fixed_properties[type] = fixed
self._available_properties[type] = available
+ # Use this function instead of _implement_channel_class.
+ def implement_channel_classes(self, type, make_channel, classes):
+ """Implement channel types in the channel manager, and add channel
+ classes that are retrieved in RequestableChannelClasses.
+
+ @type: the channel type
+ @make_channel: a function to call which returns a Channel object
+ @classes: a list of channel classes. E.g.
+
+ [ ( { '...ChannelType': '...Text', '...TargetHandleType': HANDLE_TYPE_CONTACT },
+ ['...TargetHandle'] )
+ ]
+
+ See the spec for more documentation on the
+ Requestable_Channel_Class struct.
+ """
+ self._requestable_channels[type] = make_channel
+ self._channels.setdefault(type, {})
+
+ self._requestables[type] = classes
+
def get_requestable_channel_classes(self):
"""Return all the channel types that can be created"""
retval = []
- for channel_type in self._requestable_channel_classes:
- retval.append((self._fixed_properties[channel_type],
- self._available_properties[channel_type]))
+ for channel_type in self._requestable_channels:
+ retval.extend(self._requestables.get(channel_type, []))
+
+ # _implement_channel_class was used.
+ if channel_type in self._fixed_properties:
+ retval.append((self._fixed_properties[channel_type],
+ self._available_properties.get(channel_type, [])))
+
return retval
def set_self_handle(self, handle):
self._self_handle = handle
- def get_channel_path(self):
- ret = '%s/channel%d' % (self._object_path, self._next_channel_id)
- self._next_channel_id += 1
+ def get_channel_path(self, suffix):
+ if not suffix:
+ ret = '%s/channel%d' % (self._object_path, self._next_channel_id)
+ self._next_channel_id += 1
+ else:
+ ret = '%s/%s' % (self._object_path, suffix)
return ret
def add_channels(self, channels, signal=True):
self.check_connected()
ret = []
for channel in self._channels:
- chan = (channel._object_path, channel._type, channel._get_handle_type(), channel._handle)
+ chan = (channel._object_path, channel._type, channel._handle.get_type(), channel._handle.get_id())
ret.append(chan)
return ret
# Allow TargetHandleType to be missing, but not to be otherwise broken.
check_valid_type_if_exists('TargetHandleType',
- lambda p: p > 0 and p < (2**32)-1)
+ lambda p: p >= 0 and p <= LAST_HANDLE_TYPE)
# Allow TargetType to be missing, but not to be otherwise broken.
check_valid_type_if_exists('TargetHandle',
target_id = props.get(CHANNEL_INTERFACE + '.TargetID', None)
# Handle type 0 cannot have a handle.
- if target_handle_type == HANDLE_TYPE_NONE and target_handle != None:
+ if target_handle_type == HANDLE_TYPE_NONE and target_handle not in (None, 0):
raise InvalidArgument('When TargetHandleType is NONE, ' +
- 'TargetHandle must be omitted')
+ 'TargetHandle must be omitted or 0')
# Handle type 0 cannot have a TargetID.
if target_handle_type == HANDLE_TYPE_NONE and target_id != None:
# telepathy-python - Base classes defining the interfaces of the Telepathy framework
#
-# Copyright (C) 2005,2006 Collabora Limited
+# Copyright (C) 2005,2006,2009,2010 Collabora Limited
# Copyright (C) 2005,2006 Nokia Corporation
#
# This library is free software; you can redistribute it and/or
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+from telepathy.constants import HANDLE_TYPE_NONE
+
class Handle(object):
def __init__(self, id, handle_type, name):
self._id = id
def __ne__(self, other):
return not self.__eq__(other)
+
+class NoneHandle(Handle):
+ def __init__(self):
+ Handle.__init__(self, 0, HANDLE_TYPE_NONE, '')