import telepathy
+import tp
import gtk_toolbox
import util.misc as util_misc
import handle
return prettynumber.strip()
-class AliasingMixin(telepathy.server.ConnectionInterfaceAliasing):
+class AliasingMixin(tp.ConnectionInterfaceAliasing):
USER_ALIAS_ACCOUNT = "account"
USER_ALIAS_CALLBACK = "callback"
def __init__(self):
- telepathy.server.ConnectionInterfaceAliasing.__init__(self)
+ tp.ConnectionInterfaceAliasing.__init__(self)
@property
def session(self):
# first validate that no other handle types are included
userHandleAndAlias = None
for handleId, alias in aliases.iteritems():
- h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
+ h = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
if not isinstance(h, handle.ConnectionHandle):
raise telepathy.errors.PermissionDenied("No user customizable aliases")
userHandleAndAlias = h, alias
self.AliasesChanged(changedAliases)
def _get_alias(self, handleId):
- h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
+ h = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
if isinstance(h, handle.ConnectionHandle):
if self.userAliasType == self.USER_ALIAS_CALLBACK:
aliasNumber = self.session.backend.get_callback_number()
import logging
-import telepathy
-
-import gtk_toolbox
+import tp
_moduleLogger = logging.getLogger('capabilities')
-class CapabilitiesMixin(telepathy.server.ConnectionInterfaceCapabilities):
-
- def __init__(self):
- telepathy.server.ConnectionInterfaceCapabilities.__init__(self)
- self._implement_property_get(
- telepathy.interfaces.CONN_INTERFACE_CAPABILITIES,
- {"caps": self.GetCapabilities},
- )
-
- @property
- def session(self):
- """
- @abstract
- """
- raise NotImplementedError("Abstract property called")
-
- def handle(self, handleType, handleId):
- """
- @abstract
- """
- raise NotImplementedError("Abstract function called")
-
- def GetSelfHandle(self):
- """
- @abstract
- """
- raise NotImplementedError("Abstract function called")
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def GetCapabilities(self, handleIds):
- """
- @todo HACK Remove this once we are building against a fixed version of python-telepathy
- """
- ret = []
- for handleId in handleIds:
- h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
- if handleId != 0 and (telepathy.HANDLE_TYPE_CONTACT, handleId) not in self._handles:
- raise telepathy.errors.InvalidHandle
- elif h in self._caps:
- types = self._caps[h]
- for type in types:
- for ctype, specs in types.iteritems():
- ret.append([handleId, type, specs[0], specs[1]])
- else:
- # No caps, so just default to the connection's caps
- types = self._caps[self.GetSelfHandle()]
- for type in types:
- for ctype, specs in types.iteritems():
- ret.append([handleId, type, specs[0], specs[1]])
- return ret
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def AdvertiseCapabilities(self, add, remove):
- """
- @todo HACK Remove this once we are building against a fixed version of python-telepathy
- """
- my_caps = self._caps.setdefault(self.GetSelfHandle(), {})
-
- changed = {}
- for ctype, spec_caps in add:
- changed[ctype] = spec_caps
- for ctype in remove:
- changed[ctype] = None
-
- caps = []
- for ctype, spec_caps in changed.iteritems():
- gen_old, spec_old = my_caps.get(ctype, (0, 0))
- if spec_caps is None:
- # channel type no longer supported (provider has gone away)
- gen_new, spec_new = 0, 0
- else:
- # channel type supports new capabilities
- gen_new, spec_new = gen_old, spec_old | spec_caps
- if spec_old != spec_new or gen_old != gen_new:
- caps.append((self.GetSelfHandle(), ctype, gen_old, gen_new,
- spec_old, spec_new))
-
- self.CapabilitiesChanged(caps)
- _moduleLogger.info("CapsChanged %r" % self._caps)
+class CapabilitiesMixin(tp.ConnectionInterfaceCapabilities):
- # return all my capabilities
- ret = [(ctype, caps[1]) for ctype, caps in my_caps.iteritems()]
- return ret
+ pass
import gobject
import telepathy
+import tp
import gtk_toolbox
import handle
class CallChannel(
- telepathy.server.ChannelTypeStreamedMedia,
- telepathy.server.ChannelInterfaceCallState,
- telepathy.server.ChannelInterfaceGroup,
+ tp.ChannelTypeStreamedMedia,
+ tp.ChannelInterfaceCallState,
+ tp.ChannelInterfaceGroup,
):
def __init__(self, connection, manager, props, contactHandle):
self.__props = props
self.__cancelId = None
- try:
- # HACK Older python-telepathy way
- telepathy.server.ChannelTypeStreamedMedia.__init__(self, connection, contactHandle)
- self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
- self._implement_property_get(
- telepathy.interfaces.CHANNEL_INTERFACE,
- {"Requested": lambda: self._requested}
- )
- except TypeError:
- # HACK Newer python-telepathy way
- telepathy.server.ChannelTypeStreamedMedia.__init__(self, connection, manager, props)
- telepathy.server.ChannelInterfaceCallState.__init__(self)
- telepathy.server.ChannelInterfaceGroup.__init__(self)
+ tp.ChannelTypeStreamedMedia.__init__(self, connection, manager, props)
+ tp.ChannelInterfaceCallState.__init__(self)
+ tp.ChannelInterfaceGroup.__init__(self)
self.__contactHandle = contactHandle
self._implement_property_get(
telepathy.interfaces.CHANNEL_TYPE_STREAMED_MEDIA,
},
)
- # HACK Older python-telepathy doesn't provide this
- self._immutable_properties = {
- 'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
- }
-
self.GroupFlagsChanged(0, 0)
self.MembersChanged(
'', [self._conn.GetSelfHandle()], [], [], [contactHandle],
def initial_video(self):
return False
- def get_props(self):
- # HACK Older python-telepathy doesn't provide this
- props = dict()
- for prop, iface in self._immutable_properties.items():
- props[iface + '.' + prop] = \
- self._prop_getters[iface][prop]()
- return props
-
@gtk_toolbox.log_exception(_moduleLogger)
def Close(self):
self.close()
def close(self):
- telepathy.server.ChannelTypeStreamedMedia.Close(self)
- if self.__manager.channel_exists(self.__props):
- # HACK Older python-telepathy requires doing this manually
- self.__manager.remove_channel(self)
+ tp.ChannelTypeStreamedMedia.Close(self)
self.remove_from_connection()
if self.__cancelId is not None:
gobject.source_remove(self.__cancelId)
@returns [(Stream ID, contact, stream type, stream state, stream direction, pending send flags)]
"""
- contact = self._conn.handle(telepathy.constants.HANDLE_TYPE_CONTACT, contactId)
+ contact = self._conn.get_handle_by_id(telepathy.constants.HANDLE_TYPE_CONTACT, contactId)
assert self.__contactHandle == contact, "%r != %r" % (self.__contactHandle, contact)
contactId, contactNumber = handle.ContactHandle.from_handle_name(contact.name)
import telepathy
+import tp
import util.coroutines as coroutines
import gtk_toolbox
import handle
class AllContactsListChannel(
- telepathy.server.ChannelTypeContactList,
- telepathy.server.ChannelInterfaceGroup,
+ tp.ChannelTypeContactList,
+ tp.ChannelInterfaceGroup,
):
"""
The group of contacts for whom you receive presence
"""
def __init__(self, connection, manager, props, h):
- try:
- # HACK Older python-telepathy way
- telepathy.server.ChannelTypeContactList.__init__(self, connection, h)
- self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
- self._implement_property_get(
- telepathy.interfaces.CHANNEL_INTERFACE,
- {"Requested": lambda: self._requested}
- )
- except TypeError:
- # HACK Newer python-telepathy way
- telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props)
- telepathy.server.ChannelInterfaceGroup.__init__(self)
+ tp.ChannelTypeContactList.__init__(self, connection, manager, props)
+ tp.ChannelInterfaceGroup.__init__(self)
self.__manager = manager
self.__props = props
self.__session = connection.session
- # HACK Older python-telepathy doesn't provide this
- self._immutable_properties = {
- 'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
- }
-
self._callback = coroutines.func_sink(
coroutines.expand_positional(
self._on_contacts_refreshed
self.GroupFlagsChanged(0, 0)
addressbook = connection.session.addressbook
- contacts = addressbook.get_contacts()
- self._process_refresh(addressbook, contacts, [])
+ contacts = addressbook.get_contact_ids()
+ self._process_refresh(addressbook, set(contacts), set())
- def get_props(self):
- # HACK Older python-telepathy doesn't provide this
- props = dict()
- for prop, iface in self._immutable_properties.items():
- props[iface + '.' + prop] = \
- self._prop_getters[iface][prop]()
- return props
@gtk_toolbox.log_exception(_moduleLogger)
def Close(self):
)
self._callback = None
- telepathy.server.ChannelTypeContactList.Close(self)
- if self.__manager.channel_exists(self.__props):
- # HACK Older python-telepathy requires doing this manually
- self.__manager.remove_channel(self)
+ tp.ChannelTypeContactList.Close(self)
self.remove_from_connection()
@gtk_toolbox.log_exception(_moduleLogger)
import telepathy
+import tp
import gtk_toolbox
_moduleLogger = logging.getLogger("channel.text")
-class DebugPromptChannel(telepathy.server.ChannelTypeText, cmd.Cmd):
+class DebugPromptChannel(tp.ChannelTypeText, cmd.Cmd):
"""
Look into implementing ChannelInterfaceMessages for rich text formatting
"""
cmd.Cmd.__init__(self, "Debug Prompt")
self.use_rawinput = False
- try:
- # HACK Older python-telepathy way
- telepathy.server.ChannelTypeText.__init__(self, connection, contactHandle)
- self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
- self._implement_property_get(
- telepathy.interfaces.CHANNEL_INTERFACE,
- {"Requested": lambda: self._requested}
- )
- except TypeError:
- # HACK Newer python-telepathy way
- telepathy.server.ChannelTypeText.__init__(self, connection, manager, props)
+ tp.ChannelTypeText.__init__(self, connection, manager, props)
self.__nextRecievedId = 0
self.__lastMessageTimestamp = datetime.datetime(1, 1, 1)
self.__otherHandle = contactHandle
- # HACK Older python-telepathy doesn't provide this
- self._immutable_properties = {
- 'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
- }
-
- def get_props(self):
- # HACK Older python-telepathy doesn't provide this
- props = dict()
- for prop, iface in self._immutable_properties.items():
- props[iface + '.' + prop] = \
- self._prop_getters[iface][prop]()
- return props
-
@gtk_toolbox.log_exception(_moduleLogger)
def Send(self, messageType, text):
if messageType != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
self.close()
def close(self):
- telepathy.server.ChannelTypeText.Close(self)
- if self.__manager.channel_exists(self.__props):
- # HACK Older python-telepathy requires doing this manually
- self.__manager.remove_channel(self)
+ tp.ChannelTypeText.Close(self)
self.remove_from_connection()
def _report_new_message(self, message):
import telepathy
+import tp
import util.coroutines as coroutines
import gtk_toolbox
_moduleLogger = logging.getLogger("channel.text")
-class TextChannel(telepathy.server.ChannelTypeText):
+class TextChannel(tp.ChannelTypeText):
"""
Look into implementing ChannelInterfaceMessages for rich text formatting
"""
self.__manager = manager
self.__props = props
- try:
- # HACK Older python-telepathy way
- telepathy.server.ChannelTypeText.__init__(self, connection, contactHandle)
- self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
- self._implement_property_get(
- telepathy.interfaces.CHANNEL_INTERFACE,
- {"Requested": lambda: self._requested}
- )
- except TypeError:
- # HACK Newer python-telepathy way
- telepathy.server.ChannelTypeText.__init__(self, connection, manager, props)
+ tp.ChannelTypeText.__init__(self, connection, manager, props)
self.__nextRecievedId = 0
self.__lastMessageTimestamp = datetime.datetime(1, 1, 1)
self.__otherHandle = contactHandle
- # HACK Older python-telepathy doesn't provide this
- self._immutable_properties = {
- 'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
- 'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
- }
-
self.__callback = coroutines.func_sink(
coroutines.expand_positional(
self._on_conversations_updated
else:
self._report_conversation(mergedConversations)
- def get_props(self):
- # HACK Older python-telepathy doesn't provide this
- props = dict()
- for prop, iface in self._immutable_properties.items():
- props[iface + '.' + prop] = \
- self._prop_getters[iface][prop]()
- return props
-
@gtk_toolbox.log_exception(_moduleLogger)
def Send(self, messageType, text):
if messageType != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
)
self.__callback = None
- telepathy.server.ChannelTypeText.Close(self)
- if self.__manager.channel_exists(self.__props):
- # HACK Older python-telepathy requires doing this manually
- self.__manager.remove_channel(self)
+ tp.ChannelTypeText.Close(self)
self.remove_from_connection()
@property
import dbus
import telepathy
+import tp
import channel
import util.misc as util_misc
_moduleLogger = logging.getLogger("channel_manager")
-class TelepathyChannelManager(object):
+class ChannelManager(tp.ChannelManager):
def __init__(self, connection):
- self._conn = connection
-
- self._requestable_channel_classes = dict()
- self._channels = dict()
- self._fixed_properties = dict()
- self._available_properties = dict()
-
- def close(self):
- 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:
- raise RuntimeError("Uhh, what just happened with the connection")
- self._channels[type][handle] = chan
-
- return chan
-
- 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)
+ tp.ChannelManager.__init__(self, connection)
fixed = {
telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT,
conic = None
import constants
+import tp
import util.coroutines as coroutines
import gtk_toolbox
class TheOneRingConnection(
- telepathy.server.Connection,
+ tp.Connection,
requests.RequestsMixin,
contacts.ContactsMixin,
aliasing.AliasingMixin,
raise telepathy.errors.InvalidArgument("User must specify what number GV forwards calls to")
# Connection init must come first
- telepathy.server.Connection.__init__(
+ tp.Connection.__init__(
self,
constants._telepathy_protocol_name_,
account,
def userAliasType(self):
return self.USER_ALIAS_ACCOUNT
- def handle(self, handleType, handleId):
- self.check_handle(handleType, handleId)
- return self._handles[handleType, handleId]
-
def handle_by_name(self, handleType, handleName):
requestedHandleName = handleName.encode('utf-8')
if handleType == telepathy.HANDLE_TYPE_CONTACT:
self.check_connected()
self.check_handle(handleType, handleId)
- h = self.handle(handleType, handleId) if handleId != 0 else None
+ h = self.get_handle_by_id(handleType, handleId) if handleId != 0 else None
props = self._generate_props(type, h, suppressHandler)
- if hasattr(self, "_validate_handle"):
- # HACK Newer python-telepathy
- self._validate_handle(props)
+ self._validate_handle(props)
chan = self.__channelManager.channel_for_props(props, signal=True)
path = chan._object_path
_moduleLogger.info("RequestChannel Object Path: %s" % path)
return path
- @gtk_toolbox.log_exception(_moduleLogger)
- def RequestHandles(self, handleType, names, sender):
- """
- For org.freedesktop.telepathy.Connection
- Overiding telepathy.server.Connecton to allow custom handles
- """
- self.check_connected()
- self.check_handle_type(handleType)
-
- handles = []
- for name in names:
- h = self.handle_by_name(handleType, name)
- handles.append(h)
- self.add_client_handle(h, sender)
- return handles
-
def _generate_props(self, channelType, handle, suppressHandler, initiatorHandle=None):
targetHandle = 0 if handle is None else handle.get_id()
targetHandleType = telepathy.HANDLE_TYPE_NONE if handle is None else handle.get_type()
import telepathy
import constants
+import tp
import gtk_toolbox
import connection
_moduleLogger = logging.getLogger("connection_manager")
-class TheOneRingConnectionManager(telepathy.server.ConnectionManager):
+class TheOneRingConnectionManager(tp.ConnectionManager):
def __init__(self, shutdown_func=None):
- telepathy.server.ConnectionManager.__init__(self, constants._telepathy_implementation_name_)
+ tp.ConnectionManager.__init__(self, constants._telepathy_implementation_name_)
# self._protos is from super
self._protos[constants._telepathy_protocol_name_] = connection.TheOneRingConnection
def disconnected(self, conn):
"""
- Overrides telepathy.server.ConnectionManager
+ Overrides tp.ConnectionManager
"""
- result = telepathy.server.ConnectionManager.disconnected(self, conn)
+ result = tp.ConnectionManager.disconnected(self, conn)
gobject.timeout_add(5000, self._shutdown)
def quit(self):
-import telepathy
+import tp
-class Debug(telepathy.server.Debug):
+class Debug(tp.Debug):
def __init__(self, connManager):
- telepathy.server.Debug.__init__(self, connManager)
+ tp.Debug.__init__(self, connManager)
if not force and self._contacts:
return
oldContacts = self._contacts
- oldContactIds = set(self.get_contacts())
+ oldContactIds = set(self.get_contact_ids())
self._contacts = {}
self._populate_contacts()
- newContactIds = set(self.get_contacts())
+ newContactIds = set(self.get_contact_ids())
addedContacts = newContactIds - oldContactIds
removedContacts = oldContactIds - newContactIds
message = self, addedContacts, removedContacts, changedContacts
self.updateSignalHandler.stage.send(message)
- def get_contacts(self):
+ def get_contact_ids(self):
return self._contacts.iterkeys()
def get_contact_name(self, contactId):
def find_contacts_with_number(self, queryNumber):
strippedQueryNumber = util_misc.strip_number(queryNumber)
- for contactId, (contactName, contactDetails) in self.get_contacts():
+ for contactId, (contactName, contactDetails) in self.get_contact_ids():
for phoneType, number in contactDetails:
if number == strippedQueryNumber:
yield contactId
import telepathy
+import tp
import util.misc as util_misc
_moduleLogger = logging.getLogger("handle")
-class TheOneRingHandle(telepathy.server.Handle):
+class TheOneRingHandle(tp.Handle):
"""
Instances are memoized
"""
def __init__(self, connection, id, handleType, name):
- telepathy.server.Handle.__init__(self, id, handleType, name)
+ tp.Handle.__init__(self, id, handleType, name)
self._conn = weakref.proxy(connection)
def __repr__(self):
def is_same(self, handleType, handleName):
return self.get_name() == handleName and self.get_type() == handleType
- id = property(telepathy.server.Handle.get_id)
- type = property(telepathy.server.Handle.get_type)
- name = property(telepathy.server.Handle.get_name)
+ id = property(tp.Handle.get_id)
+ type = property(tp.Handle.get_type)
+ name = property(tp.Handle.get_name)
class ConnectionHandle(TheOneRingHandle):
_moduleLogger = logging.getLogger('location')
-#class LocationMixin(telepathy.server.ConnectionInterfaceLocation):
+#class LocationMixin(tp.ConnectionInterfaceLocation):
class LocationMixin(object):
def __init__(self):
- #telepathy.server.ConnectionInterfaceLocation.__init__(self)
+ #tp.ConnectionInterfaceLocation.__init__(self)
pass
@property
import logging
-import telepathy
-
+import tp
import gtk_toolbox
import simple_presence
_moduleLogger = logging.getLogger('presence')
-class PresenceMixin(telepathy.server.ConnectionInterfacePresence, simple_presence.TheOneRingPresence):
+class PresenceMixin(tp.ConnectionInterfacePresence, simple_presence.TheOneRingPresence):
def __init__(self):
- telepathy.server.ConnectionInterfacePresence.__init__(self)
+ tp.ConnectionInterfacePresence.__init__(self)
simple_presence.TheOneRingPresence.__init__(self)
@gtk_toolbox.log_exception(_moduleLogger)
import logging
-import dbus
-import telepathy
-import gtk_toolbox
+import tp
_moduleLogger = logging.getLogger('requests')
-class RequestsMixin(
- telepathy._generated.Connection_Interface_Requests.ConnectionInterfaceRequests,
- telepathy.server.properties.DBusProperties
-):
- """
- HACK older python-telepathy doesn't provide an implementation but the new one does, ARGH
- """
+class RequestsMixin(tp.ConnectionInterfaceRequests):
- def __init__(self):
- telepathy._generated.Connection_Interface_Requests.ConnectionInterfaceRequests.__init__(self)
- telepathy.server.properties.DBusProperties.__init__(self)
-
- self._implement_property_get(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
- {'Channels': lambda: dbus.Array(self._get_channels(),
- signature='(oa{sv})'),
- 'RequestableChannelClasses': lambda: dbus.Array(
- self._channel_manager.get_requestable_channel_classes(),
- signature='(a{sv}as)')})
-
- @property
- def _channel_manager(self):
- """
- @abstract
- """
- raise NotImplementedError("Abstract property called")
-
- @property
- def handle_by_name(self, handleType, handleName):
- """
- @abstract
- """
- raise NotImplementedError("Abstract property called")
-
- def _get_channels(self):
- return [(c._object_path, c.get_props()) for c in self._channels]
-
- def _check_basic_properties(self, props):
- # ChannelType must be present and must be a string.
- if telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType' not in props or \
- not isinstance(props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType'],
- dbus.String):
- raise telepathy.errors.InvalidArgument('ChannelType is required')
-
- def check_valid_type_if_exists(prop, fun):
- p = telepathy.interfaces.CHANNEL_INTERFACE + '.' + prop
- if p in props and not fun(props[p]):
- raise telepathy.errors.InvalidArgument('Invalid %s' % prop)
-
- # 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)
-
- # Allow TargetType to be missing, but not to be otherwise broken.
- check_valid_type_if_exists('TargetHandle',
- lambda p: p > 0 and p < (2**32)-1)
- if props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle') == 0:
- raise telepathy.errors.InvalidArgument("TargetHandle may not be 0")
-
- # Allow TargetID to be missing, but not to be otherwise broken.
- check_valid_type_if_exists('TargetID',
- lambda p: isinstance(p, dbus.String))
-
- # Disallow InitiatorHandle, InitiatorID and Requested.
- check_valid_type_if_exists('InitiatorHandle', lambda p: False)
- check_valid_type_if_exists('InitiatorID', lambda p: False)
- check_valid_type_if_exists('Requested', lambda p: False)
-
- type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType']
- handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
- telepathy.constants.HANDLE_TYPE_NONE)
- handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', 0)
-
- return (type, handle_type, handle)
-
- def _validate_handle(self, props):
- target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
- telepathy.constants.HANDLE_TYPE_NONE)
- target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
- target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
-
- # Handle type 0 cannot have a handle.
- if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_handle != None:
- raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, ' +
- 'TargetHandle must be omitted')
-
- # Handle type 0 cannot have a TargetID.
- if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_id != None:
- raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, TargetID ' +
- 'must be omitted')
-
- if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
- if target_handle == None and target_id == None:
- raise telepathy.errors.InvalidArgument('When TargetHandleType is not NONE, ' +
- 'either TargetHandle or TargetID must also be given')
-
- if target_handle != None and target_id != None:
- raise telepathy.errors.InvalidArgument('TargetHandle and TargetID must not ' +
- 'both be given')
-
- self.check_handle_type(target_handle_type)
-
-
- def _alter_properties(self, props):
- target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
- telepathy.constants.HANDLE_TYPE_NONE)
- target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
- target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
-
- altered_properties = props.copy()
-
- if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
- if target_handle == None:
- # Turn TargetID into TargetHandle.
- target_handle = self.handle_by_name(target_handle_type, target_id)
- altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle'] = \
- target_handle
- else:
- # Check the supplied TargetHandle is valid
- self.check_handle(target_handle_type, target_handle)
-
- target_id = self._handles[target_handle_type,\
- target_handle].get_name()
- altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID'] = \
- target_id
-
- altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested'] = True
-
- return altered_properties
-
- @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
- in_signature='a{sv}', out_signature='oa{sv}',
- async_callbacks=('_success', '_error'))
- def CreateChannel(self, request, _success, _error):
- _moduleLogger.info("CreateChannel")
- type, handle_type, handle = self._check_basic_properties(request)
- self._validate_handle(request)
- props = self._alter_properties(request)
-
- channel = self._channel_manager.channel_for_props(props, signal=False)
-
- # Remove mutable properties
- todel = []
- for prop in props:
- iface, name = prop.rsplit('.', 1) # a bit of a hack
- if name in channel._immutable_properties:
- if channel._immutable_properties[name] != iface:
- todel.append(prop)
- else:
- todel.append(prop)
-
- for p in todel:
- del props[p]
-
- _success(channel._object_path, props)
-
- # CreateChannel MUST return *before* NewChannels is emitted.
- # @bug On older python-telepathy, it doesn't exist
- self.signal_new_channels([channel])
-
- @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
- in_signature='a{sv}', out_signature='boa{sv}',
- async_callbacks=('_success', '_error'))
- def EnsureChannel(self, request, _success, _error):
- _moduleLogger.info("EnsureChannel")
- type, handle_type, handle = self._check_basic_properties(request)
- self._validate_handle(request)
- props = self._alter_properties(request)
-
- yours = not self._channel_manager.channel_exists(props)
-
- channel = self._channel_manager.channel_for_props(props, signal=False)
-
- _success(yours, channel._object_path, props)
-
- # @bug On older python-telepathy, it doesn't exist
- self.signal_new_channels([channel])
+ pass
import telepathy
import gtk_toolbox
+import tp
import handle
import gvoice.state_machine as state_machine
"""
presences = {}
for handleId in contactIds:
- h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
+ h = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId)
if isinstance(h, handle.ConnectionHandle):
isDnd = self.session.backend.is_dnd()
if isDnd:
_moduleLogger.info("Setting Presence to '%s'" % status)
-class SimplePresenceMixin(telepathy.server.ConnectionInterfaceSimplePresence, TheOneRingPresence):
+class SimplePresenceMixin(tp.ConnectionInterfaceSimplePresence, TheOneRingPresence):
def __init__(self):
- telepathy.server.ConnectionInterfaceSimplePresence.__init__(self)
+ tp.ConnectionInterfaceSimplePresence.__init__(self)
TheOneRingPresence.__init__(self)
self._implement_property_get(
- telepathy.server.CONNECTION_INTERFACE_SIMPLE_PRESENCE,
+ tp.CONNECTION_INTERFACE_SIMPLE_PRESENCE,
{'Statuses' : self._get_statuses}
)
--- /dev/null
+"""
+telepathy-python - Base classes defining the interfaces of the Telepathy framework
+
+Copyright (C) 2005, 2006 Collabora Limited
+Copyright (C) 2005, 2006 Nokia Corporation
+Copyright (C) 2006 INdT
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+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 connmgr import *
+from conn import *
+from channel import *
+from channelmanager import *
+try:
+ from debug import *
+except ImportError:
+ pass
+from handle import *
+from media import *
+from properties import *
+
+try:
+ from telepathy._generated.Client_Observer import ClientObserver as Observer
+ from telepathy._generated.Client_Approver import ClientApprover as Approver
+ from telepathy._generated.Client_Handler import ClientHandler as Handler
+ from telepathy._generated.Client_Interface_Requests import ClientInterfaceRequests
+except ImportError:
+ pass
+
+from telepathy import version, __version__
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005, 2006 Collabora Limited
+# Copyright (C) 2005, 2006 Nokia Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 dbus
+import dbus.service
+
+from telepathy.constants import (CONNECTION_HANDLE_TYPE_NONE,
+ CHANNEL_TEXT_MESSAGE_TYPE_NORMAL)
+
+from telepathy.errors import InvalidArgument
+
+from telepathy.interfaces import (CHANNEL_INTERFACE,
+ CHANNEL_INTERFACE_DTMF,
+ CHANNEL_INTERFACE_GROUP,
+ CHANNEL_INTERFACE_HOLD,
+ CHANNEL_INTERFACE_PASSWORD,
+ CHANNEL_TYPE_CONTACT_LIST,
+ CHANNEL_TYPE_FILE_TRANSFER,
+ CHANNEL_TYPE_ROOM_LIST,
+ CHANNEL_TYPE_STREAMED_MEDIA,
+ CHANNEL_TYPE_TEXT,
+ MEDIA_SESSION_HANDLER,
+ MEDIA_STREAM_HANDLER)
+
+from telepathy._generated.Channel import Channel as _Channel
+
+from properties import DBusProperties
+
+class Channel(_Channel, DBusProperties):
+
+ def __init__(self, connection, manager, props):
+ """
+ Initialise the base channel object.
+
+ Parameters:
+ connection - the parent Connection object
+ props - initial channel properties
+ """
+ self._conn = connection
+ self._chan_manager = manager
+ object_path = self._conn.get_channel_path()
+ _Channel.__init__(self, self._conn._name, object_path)
+
+ self._type = props[CHANNEL_INTERFACE + '.ChannelType']
+ self._requested = props[CHANNEL_INTERFACE + '.Requested']
+
+ self._immutable_properties = dict()
+
+ self._handle = self._conn.get_handle_by_id(
+ props[CHANNEL_INTERFACE + '.TargetHandleType'],
+ props[CHANNEL_INTERFACE + '.TargetHandle'])
+ self._interfaces = set()
+
+ DBusProperties.__init__(self)
+ self._implement_property_get(CHANNEL_INTERFACE,
+ {'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()),
+ 'Requested': lambda: self._requested})
+
+ self._add_immutables({
+ 'ChannelType': CHANNEL_INTERFACE,
+ 'TargetHandle': CHANNEL_INTERFACE,
+ 'Interfaces': CHANNEL_INTERFACE,
+ 'TargetHandleType': CHANNEL_INTERFACE,
+ 'TargetID': CHANNEL_INTERFACE,
+ 'Requested': CHANNEL_INTERFACE
+ })
+
+ 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):
+ props = dict()
+ for prop, iface in self._immutable_properties.items():
+ props[iface + '.' + prop] = \
+ self._prop_getters[iface][prop]()
+ return props
+
+ @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='')
+ def Close(self):
+ self.Closed()
+ self._chan_manager.remove_channel(self)
+ self._conn.remove_channel(self)
+
+ @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='s')
+ def GetChannelType(self):
+ """ Returns the interface name for the type of this channel. """
+ return self._type
+
+ @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='uu')
+ def GetHandle(self):
+ """ 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)
+
+ @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as')
+ def GetInterfaces(self):
+ """
+ Get the optional interfaces implemented by the channel.
+
+ Returns:
+ an array of the D-Bus interface names
+ """
+ return self._interfaces
+
+from telepathy._generated.Channel_Type_Contact_List \
+ import ChannelTypeContactList as _ChannelTypeContactListIface
+
+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):
+ """
+ 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):
+ """
+ Initialise the channel.
+
+ Parameters:
+ connection - the parent Telepathy Connection object
+ """
+ Channel.__init__(self, connection, manager, props)
+
+
+from telepathy._generated.Channel_Type_Streamed_Media \
+ import ChannelTypeStreamedMedia as _ChannelTypeStreamedMediaIface
+
+class ChannelTypeStreamedMedia(Channel, _ChannelTypeStreamedMediaIface):
+ __doc__ = _ChannelTypeStreamedMediaIface.__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_Room_List \
+ import ChannelTypeRoomList as _ChannelTypeRoomListIface
+
+class ChannelTypeRoomList(Channel, _ChannelTypeRoomListIface):
+ __doc__ = _ChannelTypeRoomListIface.__doc__
+
+ def __init__(self, connection, manager, props):
+ """
+ Initialise the channel.
+
+ Parameters:
+ connection - the parent Telepathy Connection object
+ """
+ Channel.__init__(self, connection, manager, props)
+ self._listing_rooms = False
+ self._rooms = {}
+
+ self._add_immutables(self, {'Server': CHANNEL_TYPE_ROOM_LIST})
+
+ @dbus.service.method(CHANNEL_TYPE_ROOM_LIST, in_signature='', out_signature='b')
+ def GetListingRooms(self):
+ return self._listing_rooms
+
+ @dbus.service.signal(CHANNEL_TYPE_ROOM_LIST, signature='b')
+ def ListingRooms(self, listing):
+ self._listing_rooms = listing
+
+
+from telepathy._generated.Channel_Type_Text \
+ import ChannelTypeText as _ChannelTypeTextIface
+
+class ChannelTypeText(Channel, _ChannelTypeTextIface):
+ __doc__ = _ChannelTypeTextIface.__doc__
+
+ def __init__(self, connection, manager, props):
+ """
+ Initialise the channel.
+
+ Parameters:
+ connection - the parent Telepathy Connection object
+ """
+ Channel.__init__(self, connection, manager, props)
+
+ self._pending_messages = {}
+ self._message_types = [CHANNEL_TEXT_MESSAGE_TYPE_NORMAL]
+
+ @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='', out_signature='au')
+ def GetMessageTypes(self):
+ """
+ Return an array indicating which types of message may be sent on this
+ channel.
+
+ Returns:
+ an array of integer message types as defined above
+ """
+ return self._message_types
+
+ @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='au', out_signature='')
+ def AcknowledgePendingMessages(self, ids):
+ """
+ Inform the channel that you have handled messages by displaying them to
+ the user (or equivalent), so they can be removed from the pending queue.
+
+ Parameters:
+ ids - the message to acknowledge
+
+ Possible Errors:
+ InvalidArgument (a given message ID was not found, no action taken)
+ """
+ for id in ids:
+ if id not in self._pending_messages:
+ raise InvalidArgument("the given message ID was not found")
+
+ for id in ids:
+ del self._pending_messages[id]
+
+ @dbus.service.method(CHANNEL_TYPE_TEXT, in_signature='b', out_signature='a(uuuuus)')
+ def ListPendingMessages(self, clear):
+ """
+ List the messages currently in the pending queue, and optionally
+ remove then all.
+
+ Parameters:
+ clear - a boolean indicating whether the queue should be cleared
+
+ Returns:
+ an array of structs containing:
+ a numeric identifier
+ a unix timestamp indicating when the message was received
+ an integer handle of the contact who sent the message
+ an integer of the message type
+ a bitwise OR of the message flags
+ a string of the text of the message
+ """
+ messages = []
+ for id in self._pending_messages.keys():
+ (timestamp, sender, type, flags, text) = self._pending_messages[id]
+ message = (id, timestamp, sender, type, flags, text)
+ messages.append(message)
+ if clear:
+ del self._pending_messages[id]
+ messages.sort(cmp=lambda x,y:cmp(x[1], y[1]))
+ return messages
+
+ @dbus.service.signal(CHANNEL_TYPE_TEXT, signature='uuuuus')
+ def Received(self, id, timestamp, sender, type, flags, text):
+ self._pending_messages[id] = (timestamp, sender, type, flags, text)
+
+
+from telepathy._generated.Channel_Interface_Chat_State \
+ import ChannelInterfaceChatState
+
+
+from telepathy._generated.Channel_Interface_DTMF import ChannelInterfaceDTMF
+
+
+from telepathy._generated.Channel_Interface_Group \
+ import ChannelInterfaceGroup as _ChannelInterfaceGroup
+
+class ChannelInterfaceGroup(_ChannelInterfaceGroup, DBusProperties):
+
+ def __init__(self):
+ _ChannelInterfaceGroup.__init__(self)
+ DBusProperties.__init__(self)
+
+ self._implement_property_get(CHANNEL_INTERFACE_GROUP,
+ {'GroupFlags': lambda: dbus.UInt32(self.GetGroupFlags()),
+ 'Members': lambda: dbus.Array(self.GetMembers(), signature='u'),
+ 'RemotePendingMembers': lambda: dbus.Array(self.GetRemotePendingMembers(), signature='u'),
+ 'SelfHandle': lambda: dbus.UInt32(self.GetSelfHandle())})
+
+ self._group_flags = 0
+ self._members = set()
+ self._local_pending = set()
+ self._remote_pending = set()
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='u')
+ def GetGroupFlags(self):
+ return self._group_flags
+
+ @dbus.service.signal(CHANNEL_INTERFACE_GROUP, signature='uu')
+ def GroupFlagsChanged(self, added, removed):
+ self._group_flags |= added
+ self._group_flags &= ~removed
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
+ def GetMembers(self):
+ return self._members
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='u')
+ def GetSelfHandle(self):
+ self_handle = self._conn.GetSelfHandle()
+ if (self_handle in self._members or
+ self_handle in self._local_pending or
+ self_handle in self._remote_pending):
+ return self_handle
+ else:
+ return 0
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
+ def GetLocalPendingMembers(self):
+ return self._local_pending
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='au')
+ def GetRemotePendingMembers(self):
+ return self._remote_pending
+
+ @dbus.service.method(CHANNEL_INTERFACE_GROUP, in_signature='', out_signature='auauau')
+ def GetAllMembers(self):
+ return (self._members, self._local_pending, self._remote_pending)
+
+ @dbus.service.signal(CHANNEL_INTERFACE_GROUP, signature='sauauauauuu')
+ def MembersChanged(self, message, added, removed, local_pending, remote_pending, actor, reason):
+
+ self._members.update(added)
+ self._members.difference_update(removed)
+
+ self._local_pending.update(local_pending)
+ self._local_pending.difference_update(added)
+ self._local_pending.difference_update(removed)
+
+ self._remote_pending.update(remote_pending)
+ self._remote_pending.difference_update(added)
+ self._remote_pending.difference_update(removed)
+
+
+from telepathy._generated.Channel_Interface_Hold import ChannelInterfaceHold
+
+
+# ChannelInterfaceMediaSignalling is in telepathy.server.media
+
+
+from telepathy._generated.Channel_Interface_Password \
+ import ChannelInterfacePassword as _ChannelInterfacePassword
+
+class ChannelInterfacePassword(_ChannelInterfacePassword):
+ def __init__(self):
+ _ChannelInterfacePassword.__init__(self)
+ self._password_flags = 0
+ self._password = ''
+
+ @dbus.service.method(CHANNEL_INTERFACE_PASSWORD, in_signature='', out_signature='u')
+ def GetPasswordFlags(self):
+ return self._password_flags
+
+ @dbus.service.signal(CHANNEL_INTERFACE_PASSWORD, signature='uu')
+ def PasswordFlagsChanged(self, added, removed):
+ self._password_flags |= added
+ self._password_flags &= ~removed
+
+
+from telepathy._generated.Channel_Interface_Call_State import ChannelInterfaceCallState
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2008 Collabora Limited
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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._generated.Channel_Handler import ChannelHandler
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2009 Collabora Limited
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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.errors import NotImplemented
+
+from telepathy.interfaces import (CHANNEL_INTERFACE,
+ CHANNEL_TYPE_CONTACT_LIST,
+ CHANNEL_TYPE_TEXT)
+
+class ChannelManager(object):
+
+ def __init__(self, connection):
+ self._conn = connection
+
+ self._requestable_channel_classes = dict()
+ self._channels = dict()
+ self._fixed_properties = dict()
+ self._available_properties = dict()
+
+ def close(self):
+ for channel_type in self._requestable_channel_classes:
+ for channel in self._channels[channel_type].values():
+ if channel._type == CHANNEL_TYPE_CONTACT_LIST:
+ channel.remove_from_connection()
+ else:
+ channel.Close()
+
+ def remove_channel(self, channel):
+ for channel_type in self._requestable_channel_classes:
+ for handle, chan in self._channels[channel_type].items():
+ if channel == chan:
+ del self._channels[channel_type][handle]
+
+ def _get_type_requested_handle(self, props):
+ type = props[CHANNEL_INTERFACE + '.ChannelType']
+ requested = props[CHANNEL_INTERFACE + '.Requested']
+ target_handle = props[CHANNEL_INTERFACE + '.TargetHandle']
+ target_handle_type = props[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, _, 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]
+
+ channel = self._requestable_channel_classes[type](
+ props, **args)
+
+ self._conn.add_channels([channel], signal=signal)
+ self._channels[type][handle] = channel
+
+ return channel
+
+ 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
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005, 2006 Collabora Limited
+# Copyright (C) 2005, 2006 Nokia Corporation
+# Copyright (C) 2006 INdT
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 dbus
+import dbus.service
+import re
+import weakref
+
+from telepathy.constants import (CONNECTION_STATUS_DISCONNECTED,
+ CONNECTION_STATUS_CONNECTED,
+ HANDLE_TYPE_NONE,
+ HANDLE_TYPE_CONTACT,
+ LAST_HANDLE_TYPE)
+from telepathy.errors import (Disconnected, InvalidArgument,
+ InvalidHandle, NotAvailable,
+ NotImplemented)
+from telepathy.interfaces import (CONN_INTERFACE,
+ CONN_INTERFACE_ALIASING,
+ CONN_INTERFACE_AVATARS,
+ CONN_INTERFACE_CAPABILITIES,
+ CONN_INTERFACE_PRESENCE,
+ CONN_INTERFACE_RENAMING,
+ CONNECTION_INTERFACE_REQUESTS,
+ CHANNEL_INTERFACE)
+from handle import Handle
+from properties import DBusProperties
+
+from telepathy._generated.Connection import Connection as _Connection
+
+_BAD = re.compile(r'(?:^[0-9])|(?:[^A-Za-z0-9])')
+
+def _escape_as_identifier(name):
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ if not name:
+ return '_'
+ return _BAD.sub(lambda match: '_%02x' % ord(match.group(0)), name)
+
+class Connection(_Connection, DBusProperties):
+
+ _optional_parameters = {}
+ _mandatory_parameters = {}
+
+ def __init__(self, proto, account, manager=None):
+ """
+ Parameters:
+ proto - the name of the protcol this conection should be handling.
+ account - a protocol-specific account name
+ manager - the name of the connection manager
+ """
+
+ if manager is None:
+ import warnings
+ warnings.warn('The manager parameter to Connection.__init__ '
+ 'should be supplied', DeprecationWarning)
+ manager = 'python'
+
+ clean_account = _escape_as_identifier(account)
+ bus_name = u'org.freedesktop.Telepathy.Connection.%s.%s.%s' % \
+ (manager, proto, clean_account)
+ bus_name = dbus.service.BusName(bus_name, bus=dbus.SessionBus())
+
+ object_path = '/org/freedesktop/Telepathy/Connection/%s/%s/%s' % \
+ (manager, proto, clean_account)
+ _Connection.__init__(self, bus_name, object_path)
+
+ # monitor clients dying so we can release handles
+ dbus.SessionBus().add_signal_receiver(self.name_owner_changed_callback,
+ 'NameOwnerChanged',
+ 'org.freedesktop.DBus',
+ 'org.freedesktop.DBus',
+ '/org/freedesktop/DBus')
+
+ self._interfaces = set()
+
+ DBusProperties.__init__(self)
+ self._implement_property_get(CONN_INTERFACE,
+ {'SelfHandle': lambda: dbus.UInt32(self.GetSelfHandle())})
+
+ self._proto = proto
+
+ self._status = CONNECTION_STATUS_DISCONNECTED
+
+ self._handles = weakref.WeakValueDictionary()
+ self._next_handle_id = 1
+ self._client_handles = {}
+
+ self._channels = set()
+ self._next_channel_id = 0
+
+ def check_parameters(self, parameters):
+ """
+ Uses the values of self._mandatory_parameters and
+ self._optional_parameters to validate and type check all of the
+ provided parameters, and check all mandatory parameters are present.
+ Sets defaults according to the defaults if the client has not
+ provided any.
+ """
+ for (parm, value) in parameters.iteritems():
+ if parm in self._mandatory_parameters.keys():
+ sig = self._mandatory_parameters[parm]
+ elif parm in self._optional_parameters.keys():
+ sig = self._optional_parameters[parm]
+ else:
+ raise InvalidArgument('unknown parameter name %s' % parm)
+
+ # we currently support strings, (u)int16/32 and booleans
+ if sig == 's':
+ if not isinstance(value, unicode):
+ raise InvalidArgument('incorrect type to %s parameter, got %s, expected a string' % (parm, type(value)))
+ elif sig in 'iunq':
+ if not isinstance(value, (int, long)):
+ raise InvalidArgument('incorrect type to %s parameter, got %s, expected an int' % (parm, type(value)))
+ elif sig == 'b':
+ if not isinstance(value, bool):
+ raise InvalidArgument('incorrect type to %s parameter, got %s, expected an boolean' % (parm, type(value)))
+ else:
+ raise TypeError('unknown type signature %s in protocol parameters' % type)
+
+ for (parm, value) in self._parameter_defaults.iteritems():
+ if parm not in parameters:
+ parameters[parm] = value
+
+ missing = set(self._mandatory_parameters.keys()).difference(parameters.keys())
+ if missing:
+ raise InvalidArgument('required parameters %s not given' % missing)
+
+ def check_connected(self):
+ if self._status != CONNECTION_STATUS_CONNECTED:
+ raise Disconnected('method cannot be called unless status is CONNECTION_STATUS_CONNECTED')
+
+ def check_handle(self, handle_type, handle):
+ if (handle_type, handle) not in self._handles:
+ print "Connection.check_handle", handle, handle_type, self._handles.keys()
+ print str(list( [ self._handles[x] for x in self._handles.keys() ] ) )
+ raise InvalidHandle('handle number %d not valid for type %d' %
+ (handle, handle_type))
+
+ def check_handle_type(self, type):
+ if (type <= HANDLE_TYPE_NONE or type > LAST_HANDLE_TYPE):
+ raise InvalidArgument('handle type %s not known' % type)
+
+ def get_handle_id(self):
+ id = self._next_handle_id
+ self._next_handle_id += 1
+ return id
+
+ def add_client_handle(self, handle, sender):
+ if sender in self._client_handles:
+ self._client_handles[sender].add((handle.get_type(), handle))
+ else:
+ self._client_handles[sender] = set([(handle.get_type(), handle)])
+
+ def get_handle_by_id(self, handle_type, handle_id):
+ self.check_handle(handle_type, handle_id)
+ return self._handles[handle_type, handle_id]
+
+ def get_handle_by_name(self, handle_type, handle_name):
+ self.check_handle_type(handle_type)
+ handle = None
+
+ for candidate in self._handles.itervalues():
+ if candidate.get_name() == handle_name:
+ handle = candidate
+ break
+ else:
+ id = self.get_handle_id()
+ handle = Handle(id, handle_type, handle_name)
+ self._handles[handle_type, id] = handle
+
+ return handle
+
+ def name_owner_changed_callback(self, name, old_owner, new_owner):
+ # when name and old_owner are the same, and new_owner is
+ # blank, it is the client itself releasing its name... aka exiting
+ if (name == old_owner and new_owner == "" and name in self._client_handles):
+ print "deleting handles for", name
+ del self._client_handles[name]
+
+ 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
+ return ret
+
+ def add_channels(self, channels, signal=True):
+ """ add new channels and signal their creation"""
+ signal_channels = set()
+
+ for channel in channels:
+ if channel not in self._channels:
+ self._channels.add(channel)
+ signal_channels.add(channel)
+
+ if signal:
+ self.signal_new_channels(signal_channels)
+
+ def signal_new_channels(self, channels):
+ self.NewChannels([(channel._object_path, channel.get_props())
+ for channel in channels])
+
+ # Now NewChannel needs to be called for each new channel.
+ for channel in channels:
+ props = channel.get_props()
+
+ target_handle_type = props[CHANNEL_INTERFACE + '.TargetHandleType']
+ target_handle = props[CHANNEL_INTERFACE + '.TargetHandle']
+ suppress_handler = props[CHANNEL_INTERFACE + '.Requested']
+
+ self.NewChannel(channel._object_path, channel._type,
+ target_handle_type, target_handle,
+ suppress_handler)
+
+ def remove_channel(self, channel):
+ self._channels.remove(channel)
+ self.ChannelClosed(channel._object_path)
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='', out_signature='as')
+ def GetInterfaces(self):
+ self.check_connected()
+ return self._interfaces
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='', out_signature='s')
+ def GetProtocol(self):
+ return self._proto
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='uau', out_signature='as')
+ def InspectHandles(self, handle_type, handles):
+ self.check_connected()
+ self.check_handle_type(handle_type)
+
+ for handle in handles:
+ self.check_handle(handle_type, handle)
+
+ ret = []
+ for handle in handles:
+ ret.append(self._handles[handle_type, handle].get_name())
+
+ return ret
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='uas', out_signature='au', sender_keyword='sender')
+ def RequestHandles(self, handle_type, names, sender):
+ self.check_connected()
+ self.check_handle_type(handle_type)
+
+ ret = []
+ for name in names:
+ handle = self.get_handle_by_name(handle_type, name)
+ self.add_client_handle(handle, sender)
+ ret.append(handle.get_id())
+
+ return ret
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='uau', out_signature='', sender_keyword='sender')
+ def HoldHandles(self, handle_type, handles, sender):
+ self.check_connected()
+ self.check_handle_type(handle_type)
+
+ for handle in handles:
+ self.check_handle(handle_type, handle)
+
+ for handle in handles:
+ hand = self._handles[handle_type, handle]
+ self.add_client_handle(hand, sender)
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='uau', out_signature='', sender_keyword='sender')
+ def ReleaseHandles(self, handle_type, handles, sender):
+ self.check_connected()
+ self.check_handle_type(handle_type)
+
+ for handle in handles:
+ self.check_handle(handle_type, handle)
+ hand = self._handles[handle_type, handle]
+ if sender in self._client_handles:
+ if (handle_type, hand) not in self._client_handles[sender]:
+ raise NotAvailable('client is not holding handle %s of type %s' % (handle, handle_type))
+ else:
+ raise NotAvailable('client does not hold any handles')
+
+ for handle in handles:
+ hand = self._handles[handle_type, handle]
+ self._client_handles[sender].remove((handle_type, hand))
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='', out_signature='u')
+ def GetSelfHandle(self):
+ self.check_connected()
+ return self._self_handle
+
+ @dbus.service.signal(CONN_INTERFACE, signature='uu')
+ def StatusChanged(self, status, reason):
+ self._status = status
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='', out_signature='u')
+ def GetStatus(self):
+ return self._status
+
+ @dbus.service.method(CONN_INTERFACE, in_signature='', out_signature='a(osuu)')
+ def ListChannels(self):
+ self.check_connected()
+ ret = []
+ for channel in self._channels:
+ chan = (channel._object_path, channel._type, channel._get_handle_type(), channel._handle)
+ ret.append(chan)
+ return ret
+
+
+from telepathy._generated.Connection_Interface_Aliasing \
+ import ConnectionInterfaceAliasing
+
+
+from telepathy._generated.Connection_Interface_Avatars \
+ import ConnectionInterfaceAvatars
+
+
+from telepathy._generated.Connection_Interface_Capabilities \
+ import ConnectionInterfaceCapabilities \
+ as _ConnectionInterfaceCapabilities
+
+class ConnectionInterfaceCapabilities(_ConnectionInterfaceCapabilities):
+ def __init__(self):
+ _ConnectionInterfaceCapabilities.__init__(self)
+ # { contact handle : { str channel type : [int, int] }}
+ # the first int is the generic caps, the second is the type-specific
+ self._caps = {}
+
+ @dbus.service.method(CONN_INTERFACE_CAPABILITIES, in_signature='au', out_signature='a(usuu)')
+ def GetCapabilities(self, handles):
+ ret = []
+ handle_type = HANDLE_TYPE_CONTACT
+ for handle in handles:
+ if (handle != 0 and (handle_type, handle) not in self._handles):
+ raise InvalidHandle
+ elif handle in self._caps:
+ types = self._caps[handle]
+ for ctype, specs in types.items():
+ ret.append([handle, ctype, specs[0], specs[1]])
+ return ret
+
+ @dbus.service.signal(CONN_INTERFACE_CAPABILITIES, signature='a(usuuuu)')
+ def CapabilitiesChanged(self, caps):
+ for handle, ctype, gen_old, gen_new, spec_old, spec_new in caps:
+ self._caps.setdefault(handle, {})[ctype] = [gen_new, spec_new]
+
+ @dbus.service.method(CONN_INTERFACE_CAPABILITIES,
+ in_signature='a(su)as', out_signature='a(su)')
+ def AdvertiseCapabilities(self, add, remove):
+ my_caps = self._caps.setdefault(self._self_handle, {})
+
+ changed = {}
+ for ctype, spec_caps in add:
+ changed[ctype] = spec_caps
+ for ctype in remove:
+ changed[ctype] = None
+
+ caps = []
+ for ctype, spec_caps in changed.iteritems():
+ gen_old, spec_old = my_caps.get(ctype, (0, 0))
+ if spec_caps is None:
+ # channel type no longer supported (provider has gone away)
+ gen_new, spec_new = 0, 0
+ else:
+ # channel type supports new capabilities
+ gen_new, spec_new = gen_old, spec_old | spec_caps
+ if spec_old != spec_new or gen_old != gen_new:
+ caps.append((self._self_handle, ctype, gen_old, gen_new,
+ spec_old, spec_new))
+
+ self.CapabilitiesChanged(caps)
+
+ # return all my capabilities
+ return [(ctype, caps[1]) for ctype, caps in my_caps.iteritems()]
+
+from telepathy._generated.Connection_Interface_Requests \
+ import ConnectionInterfaceRequests \
+ as _ConnectionInterfaceRequests
+
+class ConnectionInterfaceRequests(
+ _ConnectionInterfaceRequests,
+ DBusProperties):
+
+ def __init__(self):
+ _ConnectionInterfaceRequests.__init__(self)
+ DBusProperties.__init__(self)
+
+ self._implement_property_get(CONNECTION_INTERFACE_REQUESTS,
+ {'Channels': lambda: dbus.Array(self._get_channels(),
+ signature='(oa{sv})'),
+ 'RequestableChannelClasses': lambda: dbus.Array(
+ self._channel_manager.get_requestable_channel_classes(),
+ signature='(a{sv}as)')})
+
+ def _get_channels(self):
+ return [(c._object_path, c.get_props()) for c in self._channels]
+
+ def _check_basic_properties(self, props):
+ # ChannelType must be present and must be a string.
+ if CHANNEL_INTERFACE + '.ChannelType' not in props or \
+ not isinstance(props[CHANNEL_INTERFACE + '.ChannelType'],
+ dbus.String):
+ raise InvalidArgument('ChannelType is required')
+
+ def check_valid_type_if_exists(prop, fun):
+ p = CHANNEL_INTERFACE + '.' + prop
+ if p in props and not fun(props[p]):
+ raise InvalidArgument('Invalid %s' % prop)
+
+ # 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)
+
+ # Allow TargetType to be missing, but not to be otherwise broken.
+ check_valid_type_if_exists('TargetHandle',
+ lambda p: p > 0 and p < (2**32)-1)
+ if props.get(CHANNEL_INTERFACE + '.TargetHandle') == 0:
+ raise InvalidArgument("TargetHandle may not be 0")
+
+ # Allow TargetID to be missing, but not to be otherwise broken.
+ check_valid_type_if_exists('TargetID',
+ lambda p: isinstance(p, dbus.String))
+
+ # Disallow InitiatorHandle, InitiatorID and Requested.
+ check_valid_type_if_exists('InitiatorHandle', lambda p: False)
+ check_valid_type_if_exists('InitiatorID', lambda p: False)
+ check_valid_type_if_exists('Requested', lambda p: False)
+
+ type = props[CHANNEL_INTERFACE + '.ChannelType']
+ handle_type = props.get(CHANNEL_INTERFACE + '.TargetHandleType',
+ HANDLE_TYPE_NONE)
+ handle = props.get(CHANNEL_INTERFACE + '.TargetHandle', 0)
+
+ return (type, handle_type, handle)
+
+ def _validate_handle(self, props):
+ target_handle_type = props.get(CHANNEL_INTERFACE + '.TargetHandleType',
+ HANDLE_TYPE_NONE)
+ target_handle = props.get(CHANNEL_INTERFACE + '.TargetHandle', None)
+ 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:
+ raise InvalidArgument('When TargetHandleType is NONE, ' +
+ 'TargetHandle must be omitted')
+
+ # Handle type 0 cannot have a TargetID.
+ if target_handle_type == HANDLE_TYPE_NONE and target_id != None:
+ raise InvalidArgument('When TargetHandleType is NONE, TargetID ' +
+ 'must be omitted')
+
+ if target_handle_type != HANDLE_TYPE_NONE:
+ if target_handle == None and target_id == None:
+ raise InvalidArgument('When TargetHandleType is not NONE, ' +
+ 'either TargetHandle or TargetID must also be given')
+
+ if target_handle != None and target_id != None:
+ raise InvalidArgument('TargetHandle and TargetID must not ' +
+ 'both be given')
+
+ self.check_handle_type(target_handle_type)
+
+
+ def _alter_properties(self, props):
+ target_handle_type = props.get(CHANNEL_INTERFACE + '.TargetHandleType',
+ HANDLE_TYPE_NONE)
+ target_handle = props.get(CHANNEL_INTERFACE + '.TargetHandle', None)
+ target_id = props.get(CHANNEL_INTERFACE + '.TargetID', None)
+ # Note: what the spec calls a handle, we call an ID
+ # What the spec calls an ID, we call a name
+ # What we call a handle is a handle object
+
+ altered_properties = props.copy()
+
+ if target_handle_type != HANDLE_TYPE_NONE:
+ if target_handle == None:
+ target_handle = self.get_handle_by_name(target_handle_type, target_id).get_id()
+ altered_properties[CHANNEL_INTERFACE + '.TargetHandle'] = \
+ target_handle
+ else:
+ # Check the supplied TargetHandle is valid
+ self.check_handle(target_handle_type, target_handle)
+
+ target_id = self._handles[target_handle_type,\
+ target_handle].get_name()
+ altered_properties[CHANNEL_INTERFACE + '.TargetID'] = \
+ target_id
+
+ altered_properties[CHANNEL_INTERFACE + '.Requested'] = True
+
+ return altered_properties
+
+ @dbus.service.method(CONNECTION_INTERFACE_REQUESTS,
+ in_signature='a{sv}', out_signature='oa{sv}',
+ async_callbacks=('_success', '_error'))
+ def CreateChannel(self, request, _success, _error):
+ type, handle_type, handle = self._check_basic_properties(request)
+ self._validate_handle(request)
+ props = self._alter_properties(request)
+
+ channel = self._channel_manager.channel_for_props(props, signal=False)
+
+ # Remove mutable properties
+ todel = []
+ for prop in props:
+ iface, name = prop.rsplit('.', 1) # a bit of a hack
+ if name in channel._immutable_properties:
+ if channel._immutable_properties[name] != iface:
+ todel.append(prop)
+ else:
+ todel.append(prop)
+
+ for p in todel:
+ del props[p]
+
+ _success(channel._object_path, props)
+
+ # CreateChannel MUST return *before* NewChannels is emitted.
+ self.signal_new_channels([channel])
+
+ @dbus.service.method(CONNECTION_INTERFACE_REQUESTS,
+ in_signature='a{sv}', out_signature='boa{sv}',
+ async_callbacks=('_success', '_error'))
+ def EnsureChannel(self, request, _success, _error):
+ type, handle_type, handle = self._check_basic_properties(request)
+ self._validate_handle(request)
+ props = self._alter_properties(request)
+
+ yours = not self._channel_manager.channel_exists(props)
+
+ channel = self._channel_manager.channel_for_props(props, signal=False)
+
+ _success(yours, channel._object_path, props)
+
+ self.signal_new_channels([channel])
+
+from telepathy._generated.Connection_Interface_Presence \
+ import ConnectionInterfacePresence
+
+from telepathy._generated.Connection_Interface_Simple_Presence \
+ import ConnectionInterfaceSimplePresence
+
+from telepathy._generated.Connection_Interface_Contacts \
+ import ConnectionInterfaceContacts
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005, 2006 Collabora Limited
+# Copyright (C) 2005, 2006 Nokia Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 dbus
+import dbus.service
+
+from telepathy.errors import NotImplemented
+from telepathy.interfaces import CONN_MGR_INTERFACE
+
+from telepathy._generated.Connection_Manager \
+ import ConnectionManager as _ConnectionManager
+
+class ConnectionManager(_ConnectionManager):
+ def __init__(self, name):
+ """
+ Initialise the connection manager.
+ """
+ bus_name = 'org.freedesktop.Telepathy.ConnectionManager.%s' % name
+ object_path = '/org/freedesktop/Telepathy/ConnectionManager/%s' % name
+ _ConnectionManager.__init__(self,
+ dbus.service.BusName(bus_name, dbus.Bus(), do_not_queue=True),
+ object_path)
+
+ self._connections = set()
+ self._protos = {}
+
+ def connected(self, conn):
+ """
+ Add a connection to the list of connections, emit the appropriate
+ signal.
+ """
+ self._connections.add(conn)
+ self.NewConnection(conn._name.get_name(), conn._object_path, conn._proto)
+
+ def disconnected(self, conn):
+ """
+ Remove a connection from the list of connections.
+ """
+ self._connections.remove(conn)
+ if hasattr(conn, 'remove_from_connection'):
+ # requires dbus-python >= 0.81.1
+ conn.remove_from_connection()
+ del conn
+
+ return False # when called in an idle callback
+
+ @dbus.service.method(CONN_MGR_INTERFACE, in_signature='', out_signature='as')
+ def ListProtocols(self):
+ return self._protos.keys()
+
+ def RequestConnection(self, proto, parameters):
+ if proto in self._protos:
+ conn = self._protos[proto](self, parameters)
+ self.connected(conn)
+ return (conn._name.get_name(), conn._object_path)
+ else:
+ raise NotImplemented('unknown protocol %s' % proto)
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2009 Collabora Limited
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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.interfaces import DEBUG
+from telepathy.constants import (DEBUG_LEVEL_ERROR,
+ DEBUG_LEVEL_CRITICAL,
+ DEBUG_LEVEL_WARNING,
+ DEBUG_LEVEL_INFO,
+ DEBUG_LEVEL_DEBUG)
+
+from telepathy._generated.Debug import Debug as _Debug
+from properties import DBusProperties
+
+import dbus.service
+import logging
+import sys
+import time
+
+LEVELS = {
+ logging.ERROR: DEBUG_LEVEL_ERROR,
+ logging.FATAL: DEBUG_LEVEL_CRITICAL,
+ logging.WARNING: DEBUG_LEVEL_WARNING,
+ logging.INFO: DEBUG_LEVEL_INFO,
+ logging.DEBUG: DEBUG_LEVEL_DEBUG,
+ logging.NOTSET: DEBUG_LEVEL_DEBUG
+}
+
+DEBUG_MESSAGE_LIMIT = 800
+
+class Debug(_Debug, DBusProperties, logging.Handler):
+
+ def __init__(self, conn_manager, root=''):
+ self.enabled = False
+ self._interfaces = set()
+ self._messages = []
+ object_path = '/org/freedesktop/Telepathy/debug'
+
+ _Debug.__init__(self, conn_manager._name, object_path)
+ DBusProperties.__init__(self)
+ logging.Handler.__init__(self)
+
+ self._implement_property_get(DEBUG, {'Enabled': lambda: self.enabled})
+ logging.getLogger(root).addHandler(self)
+ sys.stderr = StdErrWrapper(self, sys.stderr)
+
+ def GetMessages(self):
+ return self._messages
+
+ def add_message(self, timestamp, name, level, msg):
+ if len(self._messages) >= DEBUG_MESSAGE_LIMIT:
+ self._messages.pop()
+ self._messages.append((timestamp, name, level, msg))
+ if self.enabled:
+ self.NewDebugMessage(timestamp, name, level, msg)
+
+ # Handle logging module messages
+
+ def emit(self, record):
+ name = self.get_record_name(record)
+ level = self.get_record_level(record)
+ self.add_message(record.created, name, level, record.msg)
+
+ def get_record_level(self, record):
+ return LEVELS[record.levelno]
+
+ def get_record_name(self, record):
+ name = record.name
+ if name.contains("."):
+ domain, category = record.name.split('.', 1)
+ name = domain + "/" + category
+ return name
+
+# Wrapper around stderr so the exceptions are logged
+
+class StdErrWrapper(object):
+
+ def __init__(self, interface, stderr):
+ self._buffer = ""
+ self._interface = interface
+ self._stderr = stderr
+
+ def __getattr__(self, attr):
+ return getattr(self._stderr, attr)
+
+ def write(self, string):
+ self._stderr.write(string)
+ if '\n' not in string:
+ self._buffer += string
+ return
+
+ lines = string.split('\n')
+ lines[0] = self._buffer + lines[0]
+ self._buffer = lines[-1]
+ del lines[-1]
+
+ timestamp = time.time()
+ for line in lines:
+ self._interface.add_message(timestamp, "stderr", DEBUG_LEVEL_ERROR, line)
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005,2006 Collabora Limited
+# Copyright (C) 2005,2006 Nokia Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+class Handle(object):
+ def __init__(self, id, handle_type, name):
+ self._id = id
+ self._type = handle_type
+ self._name = name
+
+ def get_id(self):
+ return self._id
+
+ def __int__(self):
+ return int(self._id)
+
+ def __long__(self):
+ return long(self._id)
+
+ def get_type(self):
+ return self._type
+
+ def get_name(self):
+ return self._name
+
+ def __eq__(self, other):
+ return (int(self) == int(other) and self.get_type() == other.get_type())
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005,2006 Collabora Limited
+# Copyright (C) 2005,2006 Nokia Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 dbus.service
+
+from telepathy import *
+
+
+from telepathy._generated.Channel_Interface_Media_Signalling \
+ import ChannelInterfaceMediaSignalling
+from telepathy._generated.Media_Session_Handler import MediaSessionHandler
+from telepathy._generated.Media_Stream_Handler import MediaStreamHandler
--- /dev/null
+# telepathy-python - Base classes defining the interfaces of the Telepathy framework
+#
+# Copyright (C) 2005, 2006, 2008 Collabora Limited
+# Copyright (C) 2005, 2006 Nokia Corporation
+# Copyright (C) 2008 Olivier Le Thanh Duong <olivier@lethanh.be>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 dbus
+import dbus.service
+
+from telepathy.interfaces import PROPERTIES_INTERFACE
+import telepathy.errors
+
+from telepathy._generated.Properties_Interface import PropertiesInterface
+
+class DBusProperties(dbus.service.Interface):
+ def __init__(self):
+ if not getattr(self, '_interfaces', None):
+ self._interfaces = set()
+
+ self._interfaces.add(dbus.PROPERTIES_IFACE)
+
+ if not getattr(self, '_prop_getters', None):
+ self._prop_getters = {}
+ self._prop_setters = {}
+
+ def _implement_property_get(self, iface, dict):
+ self._prop_getters.setdefault(iface, {}).update(dict)
+
+ def _implement_property_set(self, iface, dict):
+ self._prop_setters.setdefault(iface, {}).update(dict)
+
+ @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
+ def Get(self, interface_name, property_name):
+ if interface_name in self._prop_getters \
+ and property_name in self._prop_getters[interface_name]:
+ return self._prop_getters[interface_name][property_name]()
+ else:
+ raise telepathy.errors.InvalidArgument()
+
+ @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ssv', out_signature='')
+ def Set(self, interface_name, property_name, value):
+ if interface_name in self._prop_setters \
+ and property_name in self._prop_setters[interface_name]:
+ return self._prop_setters[interface_name][property_name](value)
+ else:
+ raise telepathy.errors.PermissionDenied()
+
+ @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}')
+ def GetAll(self, interface_name):
+ if interface_name in self._prop_getters:
+ r = {}
+ for k, v in self._prop_getters[interface_name].items():
+ r[k] = v()
+ return r
+ else:
+ raise telepathy.errors.InvalidArgument()