import dbus PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" ACTIVITY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Activities/" ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity" 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): ret = [] for serv in self._parent.get_services_of_type(stype): ret.append(serv.object_path()) return ret @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="", out_signature="ao") def getServices(self): ret = [] for serv in self._parent.get_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="s") def getColor(self): return self._parent.get_color() @dbus.service.method(ACTIVITY_DBUS_INTERFACE, in_signature="", out_signature="ao") def getJoinedBuddies(self): ret = [] for buddy in self._parent.get_joined_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._color = None self._valid = False 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 is_valid(self): """An activity is only valid when it's color is available.""" return self._valid def get_id(self): return self._activity_id def get_color(self): return self._color 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 [] def get_joined_buddies(self): buddies = [] for serv_list in self._services.values(): for serv in serv_list: owner = serv.get_owner() if owner and not owner in buddies and owner.is_valid(): buddies.append(owner) return buddies def add_service(self, service): stype = service.get_type() if not self._services.has_key(stype): self._services[stype] = [] if not self._color: color = service.get_one_property('color') if color: self._color = color self._valid = True # 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 and serv_owner.is_valid(): 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 and serv_owner.is_valid(): serv_owner.remove_activity(self) self._dbus_helper.BuddyLeft(serv_owner.object_path())