172 lines
4.8 KiB
Python
172 lines
4.8 KiB
Python
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="s")
|
|
def getColor(self):
|
|
return self._parent.get_color()
|
|
|
|
@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._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 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 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())
|