Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Marco Pesenti Gritti 2006-07-24 11:02:10 +02:00
commit 78660bfcf6
16 changed files with 244 additions and 162 deletions

View File

@ -57,7 +57,7 @@ class BrowserActivity(Activity):
vbox.show() vbox.show()
self._pservice = PresenceService() self._pservice = PresenceService()
self._pservice.connect('ServiceAppeared', self._service_appeared_cb) self._pservice.connect('service-appeared', self._service_appeared_cb)
# Join the shared activity if we were started from one # Join the shared activity if we were started from one
if self._initial_service: if self._initial_service:

View File

@ -54,17 +54,14 @@ class ChatListener:
self._chats = {} self._chats = {}
self._pservice = PresenceService.get_instance() self._pservice = PresenceService()
self._pservice.start() self._pservice.register_service_type(BuddyChat.SERVICE_TYPE)
self._pservice.track_service_type(BuddyChat.SERVICE_TYPE)
def start(self): def start(self):
port = random.randint(5000, 65535) self._service = self._pservice.register_service(sugar.env.get_nick_name(),
service = Service.Service(sugar.env.get_nick_name(), BuddyChat.SERVICE_TYPE, BuddyChat.SERVICE_TYPE)
'local', '', port) self._buddy_stream = Stream.new_from_service(self._service)
self._buddy_stream = Stream.new_from_service(service)
self._buddy_stream.set_data_listener(self._recv_message) self._buddy_stream.set_data_listener(self._recv_message)
self._pservice.register_service(service)
def _recv_message(self, address, message): def _recv_message(self, address, message):
[nick, msg] = Chat.deserialize_message(message) [nick, msg] = Chat.deserialize_message(message)

View File

@ -36,7 +36,7 @@ class ActivitiesModel(gobject.GObject):
self._activities = [] self._activities = []
self._pservice = PresenceService() self._pservice = PresenceService()
self._pservice.connect("ActivityAppeared", self._on_activity_announced_cb) self._pservice.connect("activity-appeared", self._on_activity_announced_cb)
def add_activity(self, service): def add_activity(self, service):
activity_info = ActivityInfo(service) activity_info = ActivityInfo(service)

View File

@ -4,6 +4,9 @@ import base64
from sugar import env from sugar import env
from sugar.p2p import Stream from sugar.p2p import Stream
from sugar.presence import PresenceService
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
class ShellOwner(object): class ShellOwner(object):
"""Class representing the owner of this machine/instance. This class """Class representing the owner of this machine/instance. This class
@ -27,21 +30,12 @@ class ShellOwner(object):
fd.close() fd.close()
break break
# Our presence service # Create and announce our presence
port = random.randint(40000, 65000) self._pservice = PresenceService.PresenceService()
properties = {} self._service = self._pservice.register_service(nick, PRESENCE_SERVICE_TYPE)
print "Owner '%s' using port %d" % (nick, self._service.get_port())
# self._service = Service.Service(nick, Buddy.PRESENCE_SERVICE_TYPE, self._icon_stream = Stream.Stream.new_from_service(self._service)
# domain="", address=None, port=port, properties=properties) self._icon_stream.register_reader_handler(self._handle_buddy_icon_request, "get_buddy_icon")
# print "Owner '%s' using port %d" % (nick, port)
# self._icon_stream = Stream.Stream.new_from_service(self._service)
# self._icon_stream.register_reader_handler(self._handle_buddy_icon_request, "get_buddy_icon")
# Announce ourselves to the world
# self._pservice = PresenceService.PresenceService.get_instance()
# self._pservice.start()
# self._pservice.register_service(self._service)
def _handle_buddy_icon_request(self): def _handle_buddy_icon_request(self):
"""XMLRPC method, return the owner's icon encoded with base64.""" """XMLRPC method, return the owner's icon encoded with base64."""

View File

@ -175,6 +175,23 @@ class PresenceServiceDBusHelper(dbus.service.Object):
raise NotFoundError("Not found") raise NotFoundError("Not found")
return owner.object_path() return owner.object_path()
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="ssa{ss}sis", out_signature="o")
def registerService(self, name, stype, properties, address, port, domain):
service = self._parent.register_service(name, stype, properties, address,
port, domain)
return service.object_path()
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="s", out_signature="")
def registerServiceType(self, stype):
self._parent.register_service_type(stype)
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="s", out_signature="")
def unregisterServiceType(self, stype):
self._parent.unregister_service_type(stype)
class PresenceService(object): class PresenceService(object):
def __init__(self): def __init__(self):
@ -202,8 +219,8 @@ class PresenceService(object):
self._registered_service_types = [] self._registered_service_types = []
# Set up the dbus service we provide # Set up the dbus service we provide
session_bus = dbus.SessionBus() self._session_bus = dbus.SessionBus()
self._bus_name = dbus.service.BusName(_PRESENCE_SERVICE, bus=session_bus) self._bus_name = dbus.service.BusName(_PRESENCE_SERVICE, bus=self._session_bus)
self._dbus_helper = PresenceServiceDBusHelper(self, self._bus_name) self._dbus_helper = PresenceServiceDBusHelper(self, self._bus_name)
# Connect to Avahi for mDNS stuff # Connect to Avahi for mDNS stuff
@ -363,6 +380,11 @@ class PresenceService(object):
self._services[key] = service self._services[key] = service
else: else:
service = self._services[key] service = self._services[key]
if not service.get_address():
set_addr = service.get_one_property('address')
if not set_addr:
set_addr = address
service.set_address(set_addr)
adv.set_service(service) adv.set_service(service)
# Merge the service into our buddy and activity lists, if needed # Merge the service into our buddy and activity lists, if needed
@ -376,6 +398,9 @@ class PresenceService(object):
gobject.idle_add(self._resolve_service_reply_cb, interface, protocol, gobject.idle_add(self._resolve_service_reply_cb, interface, protocol,
name, stype, domain, host, aprotocol, address, port, txt, flags) name, stype, domain, host, aprotocol, address, port, txt, flags)
def _resolve_service_error_handler(self, err):
logging.error("error resolving service: %s" % err)
def _resolve_service(self, adv): def _resolve_service(self, adv):
"""Resolve and lookup a ZeroConf service to obtain its address and TXT records.""" """Resolve and lookup a ZeroConf service to obtain its address and TXT records."""
# Ask avahi to resolve this particular service # Ask avahi to resolve this particular service
@ -515,46 +540,37 @@ class PresenceService(object):
def _new_domain_cb_glue(self, interface, protocol, domain, flags=0): def _new_domain_cb_glue(self, interface, protocol, domain, flags=0):
gobject.idle_add(self._new_domain_cb, interface, protocol, domain, flags) gobject.idle_add(self._new_domain_cb, interface, protocol, domain, flags)
def register_service(self, name, stype, properties, address, port, domain): def register_service(self, name, stype, properties={}, address=None, port=None, domain=u"local"):
"""Register a new service, advertising it to other Buddies on the network.""" """Register a new service, advertising it to other Buddies on the network."""
objid = self._get_next_object_id()
service = Service.Service(self._bus_name, objid, name=name,
stype=stype, domain=domain, address=address, port=port,
properties=properties)
self._services[key] = service
if self.get_owner() and name != self.get_owner().get_nick_name(): if self.get_owner() and name != self.get_owner().get_nick_name():
raise RuntimeError("Tried to register a service that didn't have Owner nick as the service name!") raise RuntimeError("Tried to register a service that didn't have Owner nick as the service name!")
actid = service.get_activity_id() if not domain or not len(domain):
if actid: domain = u"local"
rs_name = Service.compose_service_name(rs_name, actid)
rs_stype = service.get_type()
rs_port = service.get_port()
rs_props = service.get_properties()
rs_domain = service.get_domain()
rs_address = service.get_address()
if not rs_domain or not len(rs_domain):
rs_domain = ""
logging.debug("registered service name '%s' type '%s' on port %d with args %s" % (rs_name, rs_stype, rs_port, rs_props))
try: try:
group = dbus.Interface(self._bus.get_object(avahi.DBUS_NAME, self._server.EntryGroupNew()), avahi.DBUS_INTERFACE_ENTRY_GROUP) obj = self._system_bus.get_object(avahi.DBUS_NAME, self._mdns_service.EntryGroupNew())
group = dbus.Interface(obj, avahi.DBUS_INTERFACE_ENTRY_GROUP)
# Add properties; ensure they are converted to ByteArray types # Add properties; ensure they are converted to ByteArray types
# because python sometimes can't figure that out # because python sometimes can't figure that out
info = [] info = []
for k, v in rs_props.items(): for k, v in properties.items():
tmp_item = "%s=%s" % (k, v) info.append(dbus.types.ByteArray("%s=%s" % (k, v)))
info.append(dbus.types.ByteArray(tmp_item))
if rs_address and len(rs_address): objid = self._get_next_object_id()
info.append("address=%s" % (rs_address)) service = Service.Service(self._bus_name, objid, name=name,
logging.debug("PS: about to call AddService for Avahi with rs_name='%s' (%s), rs_stype='%s' (%s)," \ stype=stype, domain=domain, address=address, port=port,
" rs_domain='%s' (%s), rs_port=%d (%s), info='%s' (%s)" % (rs_name, type(rs_name), rs_stype, properties=properties)
type(rs_stype), rs_domain, type(rs_domain), rs_port, type(rs_port), info, type(info))) self._services[(name, stype)] = service
group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, 0, rs_name, rs_stype, port = service.get_port()
rs_domain, "", # let Avahi figure the 'host' out
dbus.UInt16(rs_port), info,) if address and len(address):
info.append("address=%s" % (address))
logging.debug("PS: Will register service with name='%s', stype='%s'," \
" domain='%s', port=%d, info='%s'" % (name, stype, domain, port, info))
group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, 0, name, stype,
domain, "", # let Avahi figure the 'host' out
dbus.UInt16(port), info,)
group.Commit() group.Commit()
except dbus.dbus_bindings.DBusException, exc: except dbus.dbus_bindings.DBusException, exc:
# FIXME: ignore local name collisions, since that means # FIXME: ignore local name collisions, since that means
@ -562,8 +578,8 @@ class PresenceService(object):
# should un-register it an re-register with the correct info # should un-register it an re-register with the correct info
if str(exc) == "Local name collision": if str(exc) == "Local name collision":
pass pass
activity_stype = service.get_type() self.register_service_type(stype)
self.register_service_type(activity_stype) return service
def register_service_type(self, stype): def register_service_type(self, stype):
"""Requests that the Presence service look for and recognize """Requests that the Presence service look for and recognize

View File

@ -3,6 +3,7 @@ import sys, os
sys.path.insert(0, os.path.abspath("../../")) sys.path.insert(0, os.path.abspath("../../"))
from sugar import util from sugar import util
import dbus, dbus.service import dbus, dbus.service
import random
def _txt_to_dict(txt): def _txt_to_dict(txt):
"""Convert an avahi-returned TXT record formatted """Convert an avahi-returned TXT record formatted
@ -53,18 +54,6 @@ def _decompose_service_name(name):
return (None, name) return (None, name)
return (activity_id, name[:start - 2]) return (activity_id, name[:start - 2])
def is_multicast_address(address):
"""Simple numerical check for whether an IP4 address
is in the range for multicast addresses or not."""
if not address:
return False
if address[3] != '.':
return False
first = int(float(address[:3]))
if first >= 224 and first <= 239:
return True
return False
_ACTIVITY_ID_TAG = "ActivityID" _ACTIVITY_ID_TAG = "ActivityID"
SERVICE_DBUS_INTERFACE = "org.laptop.Presence.Service" SERVICE_DBUS_INTERFACE = "org.laptop.Presence.Service"
@ -86,7 +75,9 @@ class ServiceDBusHelper(dbus.service.Object):
pary['name'] = self._parent.get_name() pary['name'] = self._parent.get_name()
pary['type'] = self._parent.get_type() pary['type'] = self._parent.get_type()
pary['domain'] = self._parent.get_domain() pary['domain'] = self._parent.get_domain()
pary['activityId'] = self._parent.get_activity_id() actid = self._parent.get_activity_id()
if actid:
pary['activityId'] = actid
port = self._parent.get_port() port = self._parent.get_port()
if port: if port:
pary['port'] = self._parent.get_port() pary['port'] = self._parent.get_port()
@ -190,11 +181,6 @@ class Service(object):
def get_full_name(self): def get_full_name(self):
return self._full_name return self._full_name
def is_multicast_service(self):
"""Return True if the service's address is a multicast address,
False if it is not."""
return is_multicast_address(self._address)
def get_one_property(self, key): def get_one_property(self, key):
"""Return one property of the service, or None """Return one property of the service, or None
if the property was not found. Cannot distinguish if the property was not found. Cannot distinguish
@ -222,12 +208,14 @@ class Service(object):
# Set key/value pairs on internal property list # Set key/value pairs on internal property list
for key, value in props.items(): for key, value in props.items():
if len(key) == 0:
continue
tmp_key = key tmp_key = key
tmp_val = value tmp_val = value
if type(tmp_key) == type(u""): if type(tmp_key) != type(u""):
tmp_key = tmp_key.encode() tmp_key = unicode(tmp_key)
if type(tmp_val) == type(u""): if type(tmp_val) != type(u""):
tmp_val = tmp_val.encode() tmp_val = unicode(tmp_val)
self._properties[tmp_key] = tmp_val self._properties[tmp_key] = tmp_val
def get_type(self): def get_type(self):
@ -242,6 +230,8 @@ class Service(object):
return self._port return self._port
def set_port(self, port): def set_port(self, port):
if port == -1:
port = random.randint(4000, 65000)
if type(port) != type(1) or (port <= 1024 and port > 65536): if type(port) != type(1) or (port <= 1024 and port > 65536):
raise ValueError("must specify a valid port number between 1024 and 65536.") raise ValueError("must specify a valid port number between 1024 and 65536.")
self._port = port self._port = port
@ -257,6 +247,8 @@ class Service(object):
if type(address) != type(u""): if type(address) != type(u""):
raise ValueError("address must be unicode") raise ValueError("address must be unicode")
self._address = address self._address = address
if not self._publisher_address:
self._publisher_address = address
def get_domain(self): def get_domain(self):
"""Return the ZeroConf/mDNS domain the service was found in.""" """Return the ZeroConf/mDNS domain the service was found in."""

View File

@ -21,8 +21,8 @@ class PresenceView(gtk.VBox):
self._shell = shell self._shell = shell
self._pservice = PresenceService() self._pservice = PresenceService()
self._pservice.connect("BuddyAppeared", self._on_buddy_appeared_cb) self._pservice.connect("buddy-appeared", self._on_buddy_appeared_cb)
self._pservice.connect("BuddyDisappeared", self._on_buddy_disappeared_cb) self._pservice.connect("buddy-disappeared", self._on_buddy_disappeared_cb)
self._setup_ui() self._setup_ui()

View File

@ -1,6 +1,7 @@
import os import os
import gtk import gtk
import gobject import gobject
import time
from Shell import Shell from Shell import Shell
from Process import Process from Process import Process
@ -44,6 +45,17 @@ class MatchboxProcess(Process):
def get_name(self): def get_name(self):
return 'Matchbox' return 'Matchbox'
class PresenceServiceProcess(Process):
def __init__(self):
Process.__init__(self, "python shell/PresenceService/PresenceService.py",)
def get_name(self):
return "PresenceService"
def start(self):
Process.start(self)
time.sleep(3)
class Session: class Session:
"""Takes care of running the shell and all the sugar processes""" """Takes care of running the shell and all the sugar processes"""
@ -57,7 +69,10 @@ class Session:
process = MatchboxProcess() process = MatchboxProcess()
process.start() process.start()
process = PresenceServiceProcess()
process.start()
shell = Shell() shell = Shell()
shell.start() shell.start()

View File

@ -56,7 +56,6 @@ class Shell:
bus_name = dbus.service.BusName('com.redhat.Sugar.Shell', bus=session_bus) bus_name = dbus.service.BusName('com.redhat.Sugar.Shell', bus=session_bus)
ShellDbusService(self, bus_name) ShellDbusService(self, bus_name)
self._ps = PresenceService.PresenceService()
self._owner = ShellOwner() self._owner = ShellOwner()
self._registry = ActivityRegistry() self._registry = ActivityRegistry()

View File

@ -10,7 +10,7 @@ class ActivityChat(GroupChat):
self._chat_service = None self._chat_service = None
self._activity = activity self._activity = activity
self._pservice.connect('ServiceAppeared', self._service_appeared_cb) self._pservice.connect('service-appeared', self._service_appeared_cb)
# Find an existing activity chat to latch onto # Find an existing activity chat to latch onto
#activity_ps = self._pservice.getActivity(activity.get_id()) #activity_ps = self._pservice.getActivity(activity.get_id())

View File

@ -9,6 +9,7 @@ import dbus.glib
import gtk import gtk
import gobject import gobject
import pango import pango
import logging
from sugar.chat.Emoticons import Emoticons from sugar.chat.Emoticons import Emoticons
from sugar.chat.ChatToolbar import ChatToolbar from sugar.chat.ChatToolbar import ChatToolbar
@ -233,7 +234,7 @@ class Chat(gtk.VBox):
return return
if self._stream_writer: if self._stream_writer:
self._stream_writer.write(self.serialize_message(svgdata)) self._stream_writer.write(self.serialize_message(svgdata))
owner = PresenceService.get_instance().get_owner() owner = self._pservice.get_owner()
if owner: if owner:
self._insert_sketch(owner, svgdata) self._insert_sketch(owner, svgdata)
@ -245,12 +246,12 @@ class Chat(gtk.VBox):
self._stream_writer.write(self.serialize_message(text)) self._stream_writer.write(self.serialize_message(text))
else: else:
print 'Cannot send message, there is no stream writer' print 'Cannot send message, there is no stream writer'
owner = PresenceService.get_instance().get_owner() owner = self._pservice.get_owner()
if owner: if owner:
self._insert_rich_message(owner, text) self._insert_rich_message(owner, text)
def serialize_message(self, message): def serialize_message(self, message):
owner = PresenceService.get_instance().get_owner() owner = self._pservice.get_owner()
return owner.get_nick_name() + '||' + message return owner.get_nick_name() + '||' + message
def deserialize_message(message): def deserialize_message(message):

View File

@ -8,6 +8,18 @@ import network
from MostlyReliablePipe import MostlyReliablePipe from MostlyReliablePipe import MostlyReliablePipe
from sugar.presence import Service from sugar.presence import Service
def is_multicast_address(address):
"""Simple numerical check for whether an IP4 address
is in the range for multicast addresses or not."""
if not address:
return False
if address[3] != '.':
return False
first = int(float(address[:3]))
if first >= 224 and first <= 239:
return True
return False
class Stream(object): class Stream(object):
def __init__(self, service): def __init__(self, service):
if not service.get_port(): if not service.get_port():
@ -19,7 +31,7 @@ class Stream(object):
self._callback = None self._callback = None
def new_from_service(service, start_reader=True): def new_from_service(service, start_reader=True):
if service.is_multicast_service(): if is_multicast_address(service.get_address()):
return MulticastStream(service) return MulticastStream(service)
else: else:
return UnicastStream(service, start_reader) return UnicastStream(service, start_reader)
@ -75,28 +87,14 @@ class UnicastStream(Stream):
if start_reader: if start_reader:
self.start_reader() self.start_reader()
def start_reader(self, update_service_port=True): def start_reader(self):
"""Start the stream's reader, which for UnicastStream objects is """Start the stream's reader, which for UnicastStream objects is
and XMLRPC server. If there's a port conflict with some other and XMLRPC server. If there's a port conflict with some other
service, the reader will try to find another port to use instead. service, the reader will try to find another port to use instead.
Returns the port number used for the reader.""" Returns the port number used for the reader."""
# Set up the reader # Set up the reader
started = False self._reader = network.GlibXMLRPCServer(("", self._reader_port))
tries = 10 self._reader.register_function(self._message, "message")
self._reader = None
while not started and tries > 0:
try:
self._reader = network.GlibXMLRPCServer(("", self._reader_port))
self._reader.register_function(self._message, "message")
if update_service_port:
self._service.set_port(self._reader_port) # Update the service's port
started = True
except(socket.error):
self._reader_port = random.randint(self._reader_port + 1, 65500)
tries = tries - 1
if self._reader is None:
print 'Could not start stream reader.'
return self._reader_port
def _message(self, message): def _message(self, message):
"""Called by the XMLRPC server when network data arrives.""" """Called by the XMLRPC server when network data arrives."""

View File

@ -4,13 +4,13 @@ import dbus, dbus_bindings
class Activity(gobject.GObject): class Activity(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'BuddyJoined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'BuddyLeft': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ServiceAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ServiceDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])) ([gobject.TYPE_PYOBJECT]))
} }
@ -33,67 +33,67 @@ class Activity(gobject.GObject):
return self._object_path return self._object_path
def _emit_buddy_joined_signal(self, object_path): def _emit_buddy_joined_signal(self, object_path):
self.emit('BuddyJoined', self._ps_new_object(object_path)) self.emit('buddy-joined', self._ps_new_object(object_path))
return False return False
def _buddy_joined_cb(self, object_path): def _buddy_joined_cb(self, object_path):
gobject.idle_add(self._emit_buddy_joined_signal, object_path) gobject.idle_add(self._emit_buddy_joined_signal, object_path)
def _emit_buddy_left_signal(self, object_path): def _emit_buddy_left_signal(self, object_path):
self.emit('BuddyLeft', self._ps_new_object(object_path)) self.emit('buddy-left', self._ps_new_object(object_path))
return False return False
def _buddy_left_cb(self, object_path): def _buddy_left_cb(self, object_path):
gobject.idle_add(self._emit_buddy_left_signal, object_path) gobject.idle_add(self._emit_buddy_left_signal, object_path)
def _emit_service_appeared_signal(self, object_path): def _emit_service_appeared_signal(self, object_path):
self.emit('ServiceAppeared', self._ps_new_object(object_path)) self.emit('service-appeared', self._ps_new_object(object_path))
return False return False
def _service_appeared_cb(self, object_path): def _service_appeared_cb(self, object_path):
gobject.idle_add(self._emit_service_appeared_signal, object_path) gobject.idle_add(self._emit_service_appeared_signal, object_path)
def _emit_service_disappeared_signal(self, object_path): def _emit_service_disappeared_signal(self, object_path):
self.emit('ServiceDisappeared', self._ps_new_object(object_path)) self.emit('service-disappeared', self._ps_new_object(object_path))
return False return False
def _service_disappeared_cb(self, object_path): def _service_disappeared_cb(self, object_path):
gobject.idle_add(self._emit_service_disappeared_signal, object_path) gobject.idle_add(self._emit_service_disappeared_signal, object_path)
def getId(self): def get_id(self):
return self._activity.getId() return self._activity.getId()
def getIcon(self): def get_icon(self):
return self._buddy.getIcon() return self._buddy.getIcon()
def getServiceOfType(self, stype): def get_service_of_type(self, stype):
try: try:
object_path = self._buddy.getServiceOfType(stype) object_path = self._buddy.getServiceOfType(stype)
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._ps_new_object(object_path) return self._ps_new_object(object_path)
def getServices(self): def get_services(self):
resp = self._activity.getServices() resp = self._activity.getServices()
servs = [] servs = []
for item in resp: for item in resp:
servs.append(self._ps_new_object(item)) servs.append(self._ps_new_object(item))
return servs return servs
def getServicesOfType(self, stype): def get_services_of_type(self, stype):
resp = self._activity.getServicesOfType(stype) resp = self._activity.getServicesOfType(stype)
servs = [] servs = []
for item in resp: for item in resp:
servs.append(self._ps_new_object(item)) servs.append(self._ps_new_object(item))
return servs return servs
def getJoinedBuddies(self): def get_joined_buddies(self):
resp = self._activity.getJoinedBuddies(stype) resp = self._activity.getJoinedBuddies(stype)
buddies = [] buddies = []
for item in resp: for item in resp:
buddies.append(self._ps_new_object(item)) buddies.append(self._ps_new_object(item))
return buddies return buddies
def ownerHasJoined(self): def owner_has_joined(self):
# FIXME # FIXME
return False return False

View File

@ -1,18 +1,19 @@
import gobject import gobject
import gtk
import dbus, dbus_bindings import dbus, dbus_bindings
class Buddy(gobject.GObject): class Buddy(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'IconChanged': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([])), ([])),
'ServiceAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ServiceDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'JoinedActivity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'LeftActivity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])) ([gobject.TYPE_PYOBJECT]))
} }
@ -24,6 +25,7 @@ class Buddy(gobject.GObject):
self._object_path = object_path self._object_path = object_path
self._ps_new_object = new_obj_cb self._ps_new_object = new_obj_cb
self._ps_del_object = del_obj_cb self._ps_del_object = del_obj_cb
self._properties = {}
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path) bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE) self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE)
self._buddy.connect_to_signal('IconChanged', self._icon_changed_cb) self._buddy.connect_to_signal('IconChanged', self._icon_changed_cb)
@ -31,59 +33,83 @@ class Buddy(gobject.GObject):
self._buddy.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb) self._buddy.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb) self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb) self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
self._properties = self._buddy.getProperties()
def object_path(self): def object_path(self):
return self._object_path return self._object_path
def _emit_icon_changed_signal(self): def _emit_icon_changed_signal(self):
self.emit('IconChanged') self.emit('icon-changed')
return False return False
def _icon_changed_cb(self): def _icon_changed_cb(self):
gobject.idle_add(self._emit_icon_changed_signal) gobject.idle_add(self._emit_icon_changed_signal)
def _emit_service_appeared_signal(self, object_path): def _emit_service_appeared_signal(self, object_path):
self.emit('ServiceAppeared', self._ps_new_object(object_path)) self.emit('service-appeared', self._ps_new_object(object_path))
return False return False
def _service_appeared_cb(self, object_path): def _service_appeared_cb(self, object_path):
gobject.idle_add(self._emit_service_appeared_signal, object_path) gobject.idle_add(self._emit_service_appeared_signal, object_path)
def _emit_service_disappeared_signal(self, object_path): def _emit_service_disappeared_signal(self, object_path):
self.emit('ServiceDisappeared', self._ps_new_object(object_path)) self.emit('service-disappeared', self._ps_new_object(object_path))
return False return False
def _service_disappeared_cb(self, object_path): def _service_disappeared_cb(self, object_path):
gobject.idle_add(self._emit_service_disappeared_signal, object_path) gobject.idle_add(self._emit_service_disappeared_signal, object_path)
def _emit_joined_activity_signal(self, object_path): def _emit_joined_activity_signal(self, object_path):
self.emit('JoinedActivity', self._ps_new_object(object_path)) self.emit('joined-activity', self._ps_new_object(object_path))
return False return False
def _joined_activity_cb(self, object_path): def _joined_activity_cb(self, object_path):
gobject.idle_add(self._emit_joined_activity_signal, object_path) gobject.idle_add(self._emit_joined_activity_signal, object_path)
def _emit_left_activity_signal(self, object_path): def _emit_left_activity_signal(self, object_path):
self.emit('LeftActivity', self._ps_new_object(object_path)) self.emit('left-activity', self._ps_new_object(object_path))
return False return False
def _left_activity_cb(self, object_path): def _left_activity_cb(self, object_path):
gobject.idle_add(self._emit_left_activity_signal, object_path) gobject.idle_add(self._emit_left_activity_signal, object_path)
def getProperties(self): def _handle_property_changed_signal(self, prop_list):
return self._buddy.getProperties() self._properties = self._buddy.getProperties()
def getIcon(self): def _property_changed_cb(self, prop_list):
gobject.idle_add(self._handle_property_changed_signal, prop_list)
def get_name(self):
return self._properties['name']
def get_ip4_address(self):
return self._properties['ip4_address']
def is_owner(self):
return self._properties['owner']
def get_icon(self):
return self._buddy.getIcon() return self._buddy.getIcon()
def getServiceOfType(self, stype): def get_icon_pixbuf(self):
icon = self._buddy.getIcon()
if icon:
pbl = gtk.gdk.PixbufLoader()
pbl.write(icon)
pbl.close()
return pbl.get_pixbuf()
else:
return None
def get_service_of_type(self, stype):
try: try:
object_path = self._buddy.getServiceOfType(stype) object_path = self._buddy.getServiceOfType(stype)
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._ps_new_object(object_path) return self._ps_new_object(object_path)
def getJoinedActivities(self): def get_joined_activities(self):
try: try:
resp = self._buddy.getJoinedActivities() resp = self._buddy.getJoinedActivities()
except dbus_bindings.DBusException: except dbus_bindings.DBusException:

View File

@ -24,17 +24,17 @@ class ObjectCache(object):
class PresenceService(gobject.GObject): class PresenceService(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'BuddyAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'BuddyDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ServiceAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ServiceDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'service-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ActivityAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'ActivityDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])) ([gobject.TYPE_PYOBJECT]))
} }
@ -48,12 +48,16 @@ class PresenceService(gobject.GObject):
def __init__(self): def __init__(self):
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._obcache = ObjectCache() self._objcache = ObjectCache()
self._bus = dbus.SessionBus() self._bus = dbus.SessionBus()
self._ps = dbus.Interface(self._bus.get_object(self._PRESENCE_SERVICE, self._ps = dbus.Interface(self._bus.get_object(self._PRESENCE_SERVICE,
self._PRESENCE_OBJECT_PATH), self._PRESENCE_DBUS_INTERFACE) self._PRESENCE_OBJECT_PATH), self._PRESENCE_DBUS_INTERFACE)
self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb) self._ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb)
self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb) self._ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb)
self._ps.connect_to_signal('ServiceAppeared', self._service_appeared_cb)
self._ps.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb)
self._ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb)
self._ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb)
def _new_object(self, object_path): def _new_object(self, object_path):
obj = self._objcache.get(object_path) obj = self._objcache.get(object_path)
@ -77,100 +81,109 @@ class PresenceService(gobject.GObject):
pass pass
def _emit_buddy_appeared_signal(self, object_path): def _emit_buddy_appeared_signal(self, object_path):
self.emit('BuddyAppeared', self._new_object(object_path)) self.emit('buddy-appeared', self._new_object(object_path))
return False return False
def _buddy_appeared_cb(self, op): def _buddy_appeared_cb(self, op):
gobject.idle_add(self._emit_buddy_appeared_signal, op) gobject.idle_add(self._emit_buddy_appeared_signal, op)
def _emit_buddy_disappeared_signal(self, object_path): def _emit_buddy_disappeared_signal(self, object_path):
self.emit('BuddyDisappeared', self._ps_new_object(object_path)) self.emit('buddy-disappeared', self._new_object(object_path))
return False return False
def _buddy_disappeared_cb(self, object_path): def _buddy_disappeared_cb(self, object_path):
gobject.idle_add(self._emit_buddy_disappeared_signal, object_path) gobject.idle_add(self._emit_buddy_disappeared_signal, object_path)
def _emit_service_appeared_signal(self, object_path): def _emit_service_appeared_signal(self, object_path):
self.emit('ServiceAppeared', self._ps_new_object(object_path)) self.emit('service-appeared', self._new_object(object_path))
return False return False
def _service_appeared_cb(self, object_path): def _service_appeared_cb(self, object_path):
gobject.idle_add(self._emit_service_appeared_signal, object_path) gobject.idle_add(self._emit_service_appeared_signal, object_path)
def _emit_service_disappeared_signal(self, object_path): def _emit_service_disappeared_signal(self, object_path):
self.emit('ServiceDisappeared', self._ps_new_object(object_path)) self.emit('service-disappeared', self._new_object(object_path))
return False return False
def _service_disappeared_cb(self, object_path): def _service_disappeared_cb(self, object_path):
gobject.idle_add(self._emit_service_disappeared_signal, object_path) gobject.idle_add(self._emit_service_disappeared_signal, object_path)
def _emit_activity_appeared_signal(self, object_path): def _emit_activity_appeared_signal(self, object_path):
self.emit('ActivityAppeared', self._ps_new_object(object_path)) self.emit('activity-appeared', self._new_object(object_path))
return False return False
def _activity_appeared_cb(self, object_path): def _activity_appeared_cb(self, object_path):
gobject.idle_add(self._emit_activity_appeared_signal, object_path) gobject.idle_add(self._emit_activity_appeared_signal, object_path)
def _emit_activity_disappeared_signal(self, object_path): def _emit_activity_disappeared_signal(self, object_path):
self.emit('ActivityDisappeared', self._ps_new_object(object_path)) self.emit('activity-disappeared', self._new_object(object_path))
return False return False
def _activity_disappeared_cb(self, object_path): def _activity_disappeared_cb(self, object_path):
gobject.idle_add(self._emit_activity_disappeared_signal, object_path) gobject.idle_add(self._emit_activity_disappeared_signal, object_path)
def getServices(self): def get_services(self):
resp = self._ps.getServices() resp = self._ps.getServices()
servs = [] servs = []
for item in resp: for item in resp:
servs.append(self._new_object(item)) servs.append(self._new_object(item))
return servs return servs
def getServicesOfType(self, stype): def get_services_of_type(self, stype):
resp = self._ps.getServicesOfType(stype) resp = self._ps.getServicesOfType(stype)
servs = [] servs = []
for item in resp: for item in resp:
servs.append(self._new_object(item)) servs.append(self._new_object(item))
return servs return servs
def getActivities(self): def get_activities(self):
resp = self._ps.getActivities() resp = self._ps.getActivities()
acts = [] acts = []
for item in resp: for item in resp:
acts.append(self._new_object(item)) acts.append(self._new_object(item))
return acts return acts
def getActivity(self, activity_id): def get_activity(self, activity_id):
try: try:
act_op = self._ps.getActivity(activity_id) act_op = self._ps.getActivity(activity_id)
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._new_object(act_op) return self._new_object(act_op)
def getBuddies(self): def get_buddies(self):
resp = self._ps.getBuddies() resp = self._ps.getBuddies()
buddies = [] buddies = []
for item in resp: for item in resp:
buddies.append(self._new_object(item)) buddies.append(self._new_object(item))
return buddies return buddies
def getBuddyByName(self, name): def get_buddy_by_name(self, name):
try: try:
buddy_op = self._ps.getBuddyByName(name) buddy_op = self._ps.getBuddyByName(name)
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._new_object(buddy_op) return self._new_object(buddy_op)
def getBuddyByAddress(self, addr): def get_buddy_by_address(self, addr):
try: try:
buddy_op = self._ps.getBuddyByAddress(addr) buddy_op = self._ps.getBuddyByAddress(addr)
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._new_object(buddy_op) return self._new_object(buddy_op)
def getOwner(self): def get_owner(self):
try: try:
owner_op = self._ps.getOwner() owner_op = self._ps.getOwner()
except dbus_bindings.DBusException: except dbus_bindings.DBusException:
return None return None
return self._new_object(buddy_op) return self._new_object(owner_op)
def register_service(self, name, stype, properties={"":""}, address="", port=-1, domain=u"local"):
serv_op = self._ps.registerService(name, stype, properties, address, port, domain)
return self._new_object(serv_op)
def register_service_type(self, stype):
self._ps.registerServiceType(stype)
def unregister_service_type(self, stype):
self._ps.unregisterServiceType(stype)

View File

@ -14,12 +14,43 @@ class Service(gobject.GObject):
self._ps_del_object = del_obj_cb self._ps_del_object = del_obj_cb
sobj = bus.get_object(self._PRESENCE_SERVICE, object_path) sobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
self._service = dbus.Interface(sobj, self._SERVICE_DBUS_INTERFACE) self._service = dbus.Interface(sobj, self._SERVICE_DBUS_INTERFACE)
self._service.connect_to_signal('PropertyChanged', self._property_changed_cb)
self._props = self._service.getProperties()
def object_path(self): def object_path(self):
return self._object_path return self._object_path
def getProperties(self): def _property_changed_cb(self, prop_list):
return self._service.getProperties() self._props = self._service.getProperties()
def getPublishedValue(self, key): def get_published_value(self, key):
value = self._service.getPublishedValue(key) value = self._service.getPublishedValue(key)
def get_name(self):
return self._props['name']
def get_type(self):
return self._props['type']
def get_domain(self):
return self._props['domain']
def get_address(self):
if self._props.has_key('address'):
return self._props['address']
return None
def get_activity_id(self):
if self._props.has_key('activityId'):
return self._props['activityId']
return None
def get_port(self):
if self._props.has_key('port'):
return self._props['port']
return None
def get_source_address(self):
if self._props.has_key('sourceAddress'):
return self._props['sourceAddress']
return None