import dbus PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" ACTIVITY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Activities/" ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity" class NotFoundError(Exception): pass class ActivityDBusHelper(dbus.service.Object): def __init__(self, parent, bus_name, object_path): self._parent = parent self._bus_name = bus_name self._object_path = object_path dbus.service.Object.__init__(self, bus_name, self._object_path) @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="s", out_signature="ao") def getServicesOfType(self, stype): services = self._parent.get_services_of_type(stype) if not services: raise NotFoundError("Not found") ret = [] for serv in services: ret.append(serv.object_path()) return ret @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="", out_signature="ao") def getServices(self): services = self._parent.get_services() if not services: raise NotFoundError("Not found") ret = [] for serv in services: ret.append(serv.object_path()) return ret @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="", out_signature="s") def getId(self): return self._parent.get_id() @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="", out_signature="ao") def getJoinedBuddies(self): buddies = self._parent.get_joined_buddies() if not buddies: raise NotFoundError("Not found") ret = [] for buddy in buddies: ret.append(buddy.object_path()) return ret @dbus.service.signal(ACTIVITY_DBUS_INTERFACE, signature="o") def ServiceAppeared(self, object_path): pass @dbus.service.signal(ACTIVITY_DBUS_INTERFACE, signature="o") def ServiceDisappeared(self, object_path): pass @dbus.service.signal(ACTIVITY_DBUS_INTERFACE, signature="o") def BuddyJoined(self, object_path): pass @dbus.service.signal(ACTIVITY_DBUS_INTERFACE, signature="o") def BuddyLeft(self, object_path): pass class Activity(object): def __init__(self, bus_name, object_id, initial_service): if not initial_service.get_activity_id(): raise ValueError("Service must have a valid Activity ID") self._activity_id = initial_service.get_activity_id() self._buddies = [] self._services = {} # service type -> list of Services self._object_id = object_id self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id self._dbus_helper = ActivityDBusHelper(self, bus_name, self._object_path) self.add_service(initial_service) def object_path(self): return dbus.ObjectPath(self._object_path) def get_id(self): return self._activity_id def get_services(self): ret = [] for serv_list in self._services.values(): for service in serv_list: if service not in ret: ret.append(service) return ret def get_services_of_type(self, stype): if self._services.has_key(stype): return self._services[stype] return None def get_joined_buddies(self): buddies = [] for serv_list in self._services.values(): for serv in serv_list: owner = serv.get_owner() if not owner in buddies: buddies.append(owner) return buddies def add_service(self, service): stype = service.get_type() if not self._services.has_key(stype): self._services[stype] = [] # Send out the BuddyJoined signal if this is the first # service from the buddy that we've seen buddies = self.get_joined_buddies() serv_owner = service.get_owner() if serv_owner and serv_owner not in buddies: self._dbus_helper.BuddyJoined(serv_owner.object_path()) serv_owner.add_activity(self) if not service in self._services[stype]: self._services[stype].append(service) self._dbus_helper.ServiceAppeared(service.object_path()) def remove_service(self, service): stype = service.get_type() if not self._services.has_key(stype): return self._services[stype].remove(service) self._dbus_helper.ServiceDisappeared(service.object_path()) if len(self._services[stype]) == 0: del self._services[stype] # Send out the BuddyLeft signal if this is the last # service from the buddy buddies = self.get_joined_buddies() serv_owner = service.get_owner() if serv_owner and serv_owner not in buddies: serv_owner.remove_activity(self) self._dbus_helper.BuddyLeft(serv_owner.object_path())