X-Git-Url: http://git.maemo.org/git/?p=theonering;a=blobdiff_plain;f=src%2Fsimple_presence.py;h=c71a5c249fb65c401c44f2eed81a9250267f2330;hp=4f1c09b788d6c5c886a59725987f55e49d4cdd7b;hb=d4b136496c94a847232c2454a0732984aa43e56d;hpb=ab4da214c520d763bbbddeb828c8e7c838374fe3 diff --git a/src/simple_presence.py b/src/simple_presence.py index 4f1c09b..c71a5c2 100644 --- a/src/simple_presence.py +++ b/src/simple_presence.py @@ -1,139 +1,132 @@ import logging +import dbus import telepathy +import util.misc as misc_utils +import tp +import handle +import gvoice.state_machine as state_machine -class ButterflyPresenceMapping(object): + +_moduleLogger = logging.getLogger(__name__) + + +class TheOneRingPresence(object): + + # Note: these strings are also in the theonering.profile file ONLINE = 'available' AWAY = 'away' - BUSY = 'dnd' - IDLE = 'xa' - BRB = 'brb' - PHONE = 'phone' - LUNCH = 'lunch' - INVISIBLE = 'hidden' + HIDDEN = 'hidden' OFFLINE = 'offline' - to_pymsn = { - ONLINE: pymsn.Presence.ONLINE, - AWAY: pymsn.Presence.AWAY, - BUSY: pymsn.Presence.BUSY, - IDLE: pymsn.Presence.IDLE, - BRB: pymsn.Presence.BE_RIGHT_BACK, - PHONE: pymsn.Presence.ON_THE_PHONE, - LUNCH: pymsn.Presence.OUT_TO_LUNCH, - INVISIBLE: pymsn.Presence.INVISIBLE, - OFFLINE: pymsn.Presence.OFFLINE + TO_PRESENCE_TYPE = { + ONLINE: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE), + AWAY: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY), + HIDDEN: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN), + OFFLINE: dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE), } - to_telepathy = { - pymsn.Presence.ONLINE: ONLINE, - pymsn.Presence.AWAY: AWAY, - pymsn.Presence.BUSY: BUSY, - pymsn.Presence.IDLE: IDLE, - pymsn.Presence.BE_RIGHT_BACK: BRB, - pymsn.Presence.ON_THE_PHONE: PHONE, - pymsn.Presence.OUT_TO_LUNCH: LUNCH, - pymsn.Presence.INVISIBLE: INVISIBLE, - pymsn.Presence.OFFLINE: OFFLINE - } + @property + def session(self): + """ + @abstract + """ + raise NotImplementedError() + + def Disconnect(self): + """ + @abstract + """ + raise NotImplementedError("Abstract function called") + + def get_handle_by_id(self, handleType, handleId): + """ + @abstract + """ + raise NotImplementedError("Abstract function called") + + def get_presences(self, contactIds): + """ + @return {ContactHandle: (Status, Presence Type, Message)} + """ + presences = {} + for handleId in contactIds: + h = self.get_handle_by_id(telepathy.HANDLE_TYPE_CONTACT, handleId) + if isinstance(h, handle.ConnectionHandle): + isDnd = self.session.is_dnd() + if isDnd: + presence = TheOneRingPresence.HIDDEN + else: + state = self.session.stateMachine.state + if state == state_machine.StateMachine.STATE_ACTIVE: + presence = TheOneRingPresence.ONLINE + elif state == state_machine.StateMachine.STATE_IDLE: + presence = TheOneRingPresence.AWAY + else: + raise telepathy.errors.InvalidArgument("Unsupported state on the state machine: %s" % state) + presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence] + else: + presence = TheOneRingPresence.AWAY + presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence] - to_presence_type = { - ONLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE, - AWAY: telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY, - BUSY: telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY, - IDLE: telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, - BRB: telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY, - PHONE: telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY, - LUNCH: telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, - INVISIBLE: telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN, - OFFLINE: telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE - } + presences[h] = (presenceType, presence) + return presences + def set_presence(self, status): + if status == self.ONLINE: + self.session.set_dnd(False) + self.session.stateMachine.set_state(state_machine.StateMachine.STATE_ACTIVE) + elif status == self.AWAY: + self.session.stateMachine.set_state(state_machine.StateMachine.STATE_IDLE) + elif status == self.HIDDEN: + self.session.set_dnd(True) + elif status == self.OFFLINE: + self.Disconnect() + else: + raise telepathy.errors.InvalidArgument("Unsupported status: %r" % status) + _moduleLogger.info("Setting Presence to '%s'" % status) -class ButterflySimplePresence(telepathy.server.ConnectionInterfaceSimplePresence): - def __init__(self): - telepathy.server.ConnectionInterfaceSimplePresence.__init__(self) +class SimplePresenceMixin(tp.ConnectionInterfaceSimplePresence, TheOneRingPresence): - dbus_interface = 'org.freedesktop.Telepathy.Connection.Interface.SimplePresence' + def __init__(self): + tp.ConnectionInterfaceSimplePresence.__init__(self) + TheOneRingPresence.__init__(self) - self._implement_property_get(dbus_interface, {'Statuses' : self.get_statuses}) + self._implement_property_get( + tp.CONNECTION_INTERFACE_SIMPLE_PRESENCE, + {'Statuses' : self._get_statuses} + ) + @misc_utils.log_exception(_moduleLogger) def GetPresences(self, contacts): - return self.get_simple_presences(contacts) - + """ + @return {ContactHandle: (Status, Presence Type, Message)} + """ + personalMessage = u"" + return dbus.Dictionary( + ( + (h, dbus.Struct((presenceType, presence, personalMessage), signature="uss")) + for (h, (presenceType, presence)) in self.get_presences(contacts).iteritems() + ), + signature="u(uss)" + ) + + @misc_utils.log_exception(_moduleLogger) def SetPresence(self, status, message): - if status == ButterflyPresenceMapping.OFFLINE: - self.Disconnect() - - try: - presence = ButterflyPresenceMapping.to_pymsn[status] - except KeyError: - raise telepathy.errors.InvalidArgument - message = message.encode("utf-8") - - logging.info("Setting Presence to '%s'" % presence) - logging.info("Setting Personal message to '%s'" % message) - - if self._status != telepathy.CONNECTION_STATUS_CONNECTED: - self._initial_presence = presence - self._initial_personal_message = message - else: - self.msn_client.profile.personal_message = message - self.msn_client.profile.presence = presence - - def get_simple_presences(self, contacts): - presences = {} - for handle_id in contacts: - handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handle_id) - try: - contact = handle.contact - except AttributeError: - contact = handle.profile - - if contact is not None: - presence = ButterflyPresenceMapping.to_telepathy[contact.presence] - personal_message = unicode(contact.personal_message, "utf-8") - else: - presence = ButterflyPresenceMapping.OFFLINE - personal_message = u"" - - presence_type = ButterflyPresenceMapping.to_presence_type[presence] + if message: + raise telepathy.errors.InvalidArgument("Messages aren't supported") - presences[handle] = (presence_type, presence, personal_message) - return presences + self.set_presence(status) - def get_statuses(self): - # you get one of these for each status - # {name:(Type, May_Set_On_Self, Can_Have_Message} - return { - ButterflyPresenceMapping.ONLINE:( - telepathy.CONNECTION_PRESENCE_TYPE_AVAILABLE, - True, True), - ButterflyPresenceMapping.AWAY:( - telepathy.CONNECTION_PRESENCE_TYPE_AWAY, - True, True), - ButterflyPresenceMapping.BUSY:( - telepathy.CONNECTION_PRESENCE_TYPE_AWAY, - True, True), - ButterflyPresenceMapping.IDLE:( - telepathy.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, - True, True), - ButterflyPresenceMapping.BRB:( - telepathy.CONNECTION_PRESENCE_TYPE_AWAY, - True, True), - ButterflyPresenceMapping.PHONE:( - telepathy.CONNECTION_PRESENCE_TYPE_AWAY, - True, True), - ButterflyPresenceMapping.LUNCH:( - telepathy.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, - True, True), - ButterflyPresenceMapping.INVISIBLE:( - telepathy.CONNECTION_PRESENCE_TYPE_HIDDEN, - True, False), - ButterflyPresenceMapping.OFFLINE:( - telepathy.CONNECTION_PRESENCE_TYPE_OFFLINE, - True, False) - } + def _get_statuses(self): + """ + Property mapping presence statuses available to the corresponding presence types + @returns {Name: (Telepathy Type, May Set On Self, Can Have Message)} + """ + return dict( + (localType, (telepathyType, True, False)) + for (localType, telepathyType) in self.TO_PRESENCE_TYPE.iteritems() + )