diff --git a/services/presence2/activity.py b/services/presence2/activity.py index 27e372bd..7010d1bb 100644 --- a/services/presence2/activity.py +++ b/services/presence2/activity.py @@ -21,11 +21,11 @@ _ACTIVITY_PATH = "/org/laptop/Sugar/Presence/Activities/" _ACTIVITY_INTERFACE = "org.laptop.Sugar.Presence.Activity" class Activity(dbus.service.Object): - def __init__(self, bus_name, object_id): + def __init__(self, bus_name, object_id, activity_id): self._buddies = [] self._color = None self._valid = False - self._activity_id = None + self._activity_id = activity_id self._object_id = object_id self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id @@ -90,3 +90,16 @@ class Activity(dbus.service.Object): def get_color(self): return self._color + + def get_joined_buddies(self): + return self._buddies + + def buddy_joined(self, buddy): + if buddy not in self._buddies: + self._buddies.append(buddy) + self.BuddyJoined(buddy.object_path()) + + def buddy_left(self, buddy): + if buddy in self._buddies: + self._buddies.remove(buddy) + self.BuddyLeft(buddy.object_path()) diff --git a/services/presence2/buddy.py b/services/presence2/buddy.py index 458d1247..f9946b5d 100644 --- a/services/presence2/buddy.py +++ b/services/presence2/buddy.py @@ -71,7 +71,6 @@ class Buddy(DBusGObject): self._valid = False self._owner = False self._key = None - self._icon = '' gobject.GObject.__init__(self, **kwargs) if not self._key: diff --git a/services/presence2/presenceservice.py b/services/presence2/presenceservice.py index 7ffd923c..47bcdea7 100644 --- a/services/presence2/presenceservice.py +++ b/services/presence2/presenceservice.py @@ -43,7 +43,7 @@ class PresenceService(dbus.service.Object): self._next_object_id = 0 self._buddies = {} # key -> Buddy - self._handles = {} # tp client -> (handle -> Buddy) + self._handles_buddies = {} # tp client -> (handle -> Buddy) self._activities = {} # activity id -> Activity bus = dbus.SessionBus() @@ -59,19 +59,19 @@ class PresenceService(dbus.service.Object): # Set up the server connection self._server_plugin = ServerPlugin(self._registry) - self._handles[self._server_plugin] = {} + self._handles_buddies[self._server_plugin] = {} self._server_plugin.connect('status', self._server_status_cb) self._server_plugin.connect('contact-online', self._contact_online) self._server_plugin.connect('contact-offline', self._contact_offline) self._server_plugin.connect('avatar-updated', self._avatar_updated) self._server_plugin.connect('properties-changed', self._properties_changed) - self._server_plugin.connect('activities-changed', self._activities_changed) + self._server_plugin.connect('contact-activities-changed', self._contact_activities_changed) self._server_plugin.start() # Set up the link local connection self._ll_plugin = LinkLocalPlugin(self._registry) - self._handles[self._ll_plugin] = {} + self._handles_buddies[self._ll_plugin] = {} dbus.service.Object.__init__(self, self._bus_name, _PRESENCE_PATH) @@ -89,7 +89,7 @@ class PresenceService(dbus.service.Object): buddy.connect("validity-changed", self._buddy_validity_changed_cb) self._buddies[key] = buddy - buddies = self._handles[tp] + buddies = self._handles_buddies[tp] buddies[handle] = buddy # store the handle of the buddy for this CM buddy.handles[tp] = handle @@ -105,7 +105,7 @@ class PresenceService(dbus.service.Object): print "Buddy left: %s (%s)" % (buddy.props.nick, buddy.props.color) def _contact_offline(self, tp, handle): - buddy = self._handles[tp].pop(handle) + buddy = self._handles_buddies[tp].pop(handle) key = buddy.props.key # the handle of the buddy for this CM is not valid anymore @@ -122,19 +122,80 @@ class PresenceService(dbus.service.Object): return self._next_object_id def _avatar_updated(self, tp, handle, avatar): - buddy = self._handles[tp].get(handle) + buddy = self._handles_buddies[tp].get(handle) if buddy and not buddy.props.owner: print "Buddy %s icon updated" % buddy.props.key buddy.props.icon = avatar def _properties_changed(self, tp, handle, prop): - buddy = self._handles[tp].get(handle) + buddy = self._handles_buddies[tp].get(handle) if buddy: buddy.set_properties(prop) print "Buddy %s properties updated" % buddy.props.key - def _activities_changed(self, tp, handle, prop): - pass + def _new_activity(self, activity_id): + objid = self._get_next_object_id() + activity = Activity(self._bus_name, objid, activity_id) + # FIXME : don't do that shit ! + activity._valid = True + self._activities[activity_id] = activity + + print "new activity", activity_id + self.ActivityAppeared(activity.object_path()) + + return activity + + def _remove_activity(self, activity): + print "remove activity", activity.get_id() + + self.ActivityDisappeared(activity.object_path()) + del self._activities[activity.get_id()] + + def _contact_activities_changed(self, tp, contact_handle, activities): + print "------------activities changed-------------" + buddies = self._handles_buddies[tp] + buddy = buddies.get(contact_handle) + + if not buddy: + # We don't know this buddy + # FIXME: What should we do here? + # FIXME: Do we need to check if the buddy is valid or something? + print "contact_activities_changed: buddy unknow" + return + + old_activities = set() + for activity in buddy.get_joined_activities(): + old_activities.add(activity.get_id()) + + new_activities = set(activities) + + activities_joined = new_activities - old_activities + for act in activities_joined: + print "buddy", contact_handle, "joined", act + activity = self._activities.get(act) + if not activity: + # new activity + activity = self._new_activity(act) + + activity.buddy_joined(buddy) + buddy.add_activity(activity) + + activities_left = old_activities - new_activities + for act in activities_left: + print "buddy", contact_handle, "left", act + activity = self._activities.get(act) + if not activity: + continue + + activity.buddy_left(buddy) + buddy.remove_activity(activity) + + if not activity.get_joined_buddies(): + self._remove_activity(activity) + + # current activity + if len(activities) > 0: + buddy.set_properties({'current-activity':activities[0]}) @dbus.service.signal(_PRESENCE_INTERFACE, signature="o") def ActivityAppeared(self, activity): @@ -190,7 +251,7 @@ class PresenceService(dbus.service.Object): raise NotImplementedError("not implemented yet") def cleanup(self): - for tp in self._handles: + for tp in self._handles_buddies: tp.cleanup() def main(): diff --git a/services/presence2/server_plugin.py b/services/presence2/server_plugin.py index 056ede97..5ca12fd4 100644 --- a/services/presence2/server_plugin.py +++ b/services/presence2/server_plugin.py @@ -33,7 +33,7 @@ from telepathy.interfaces import ( from telepathy.constants import ( CONNECTION_HANDLE_TYPE_NONE, CONNECTION_HANDLE_TYPE_CONTACT, CONNECTION_STATUS_CONNECTED, CONNECTION_STATUS_DISCONNECTED, CONNECTION_STATUS_CONNECTING, - CONNECTION_HANDLE_TYPE_LIST, CONNECTION_HANDLE_TYPE_CONTACT, + CONNECTION_HANDLE_TYPE_LIST, CONNECTION_HANDLE_TYPE_CONTACT,CONNECTION_HANDLE_TYPE_ROOM, CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED) CONN_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' @@ -82,7 +82,7 @@ class ServerPlugin(gobject.GObject): ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), 'properties-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - 'activities-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + 'contact-activities-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])) } @@ -93,6 +93,7 @@ class ServerPlugin(gobject.GObject): self._gabble_mgr = registry.GetManager('gabble') self._online_contacts = {} # handle -> jid + self._activities = {} # activity id -> handle self._account = self._get_account_info() self._conn = self._init_connection() @@ -263,6 +264,8 @@ class ServerPlugin(gobject.GObject): self_handle = self._conn[CONN_INTERFACE].GetSelfHandle() self._conn[CONN_INTERFACE_ALIASING].SetAliases( {self_handle : name} ) + self._conn[CONN_INTERFACE_BUDDY_INFO].SetActivities([]) + self._upload_avatar() def _status_changed_cb(self, state, reason): @@ -343,6 +346,9 @@ class ServerPlugin(gobject.GObject): self._online_contacts[handle] = jid self.emit("contact-online", handle, props) + activities = self._conn[CONN_INTERFACE_BUDDY_INFO].GetActivities(handle) + self._activities_changed_cb(handle, activities) + def _presence_update_cb(self, presence): for handle in presence: timestamp, statuses = presence[handle] @@ -379,4 +385,7 @@ class ServerPlugin(gobject.GObject): self.emit("properties-changed", contact, properties) def _activities_changed_cb(self, contact, activities): - self.emit("activities-changed", contact, activities) + for act_id, act_handle in activities: + self._activities[act_id] = act_handle + activities_id = map(lambda x: x[0], activities) + self.emit("contact-activities-changed", contact, activities_id) diff --git a/shell/intro/intro.py b/shell/intro/intro.py index 75e3791d..83c88da8 100644 --- a/shell/intro/intro.py +++ b/shell/intro/intro.py @@ -15,6 +15,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import gtk, gobject +import dbus import hippo import logging from gettext import gettext as _ @@ -100,11 +101,28 @@ class VideoBox(hippo.CanvasBox, hippo.CanvasItem): self._label.props.font_desc = font.DEFAULT.get_pango_desc() self.append(self._label) + # check for camera and if not generate a .jpg + has_webcam = False try: - import glive - self._video = glive.LiveVideoSlot(_VIDEO_WIDTH, _VIDEO_HEIGHT) - except ImportError: - self._video = IntroFallbackVideo() + sys_bus = dbus.SystemBus() + hal_obj = sys_bus.get_object ('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') + hal = dbus.Interface (hal_obj, 'org.freedesktop.Hal.Manager') + + udis = hal.FindDeviceByCapability ('video4linux') + + # check for the olpc specific camera + if not udis: + udis = hal.FindDeviceStringMatch('info.linux.driver','cafe1000-ccic') + + if udis: + has_webcam = True + + finally: + if has_webcam: + import glive + self._video = glive.LiveVideoSlot(_VIDEO_WIDTH, _VIDEO_HEIGHT) + else: + self._video = IntroFallbackVideo() self._video.set_size_request(_VIDEO_WIDTH, _VIDEO_HEIGHT) self._video.connect('pixbuf', self._new_pixbuf_cb) diff --git a/shell/model/MeshModel.py b/shell/model/MeshModel.py index fb51912f..b2c49bb5 100644 --- a/shell/model/MeshModel.py +++ b/shell/model/MeshModel.py @@ -100,7 +100,7 @@ class MeshModel(gobject.GObject): self._add_access_point(nm_device, nm_network) def _nm_network_disappeared_cb(self, nm_device, nm_network): - self._remove_access_point(nm_device, nm_network) + self._remove_access_point(nm_network) def _add_network_device(self, nm_device): for nm_network in nm_device.get_networks(): diff --git a/shell/view/Shell.py b/shell/view/Shell.py index c032831d..99c940f5 100644 --- a/shell/view/Shell.py +++ b/shell/view/Shell.py @@ -55,7 +55,7 @@ class Shell(gobject.GObject): self._frame = Frame(self) self._frame.show_and_hide(3) - self.start_activity('org.laptop.JournalActivity') + #self.start_activity('org.laptop.JournalActivity') def _activity_added_cb(self, home_model, home_activity): activity_host = ActivityHost(home_activity) diff --git a/sugar/activity/activityfactory.py b/sugar/activity/activityfactory.py index 7901ed2e..695d149c 100644 --- a/sugar/activity/activityfactory.py +++ b/sugar/activity/activityfactory.py @@ -70,7 +70,7 @@ class ActivityCreationHandler(gobject.GObject): bundle = registry.get_bundle(service_name) bus = dbus.SessionBus() - proxy_obj = bus.get_object(service_name, bundle.get_object_path()) + proxy_obj = bus.get_object(service_name, bundle.get_object_path(), follow_name_owner_changes=True) factory = dbus.Interface(proxy_obj, "com.redhat.Sugar.ActivityFactory") factory.create(self._activity_handle.get_dict(), diff --git a/tools/build-snapshot.sh b/tools/build-snapshot.sh index 637773ef..cbcb6564 100755 --- a/tools/build-snapshot.sh +++ b/tools/build-snapshot.sh @@ -1,6 +1,6 @@ VERSION=0.63 DATE=`date +%Y%m%d` -RELEASE=2.38 +RELEASE=2.42 TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2 rm sugar-$VERSION.tar.bz2