<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.sugarlabs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bert</id>
	<title>Sugar Labs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.sugarlabs.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bert"/>
	<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/go/Special:Contributions/Bert"/>
	<updated>2026-04-16T06:39:12Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=79001</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=79001"/>
		<updated>2012-06-05T15:25:33Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* External Media */ media -&amp;gt; volumes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
&amp;lt;strike&amp;gt;&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data. Use the [[#External Media|external media API]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal. No access restrictions are applied currently. If activities use these external volumes directly, they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
Depending on the Linux distro version, the volumes appear as /mnt/*, /media/*, /run/media/$USER/*, or in other places. Sugar up to version 0.82 provided an API to access their [[#Mount Points|mount points]]. Nowadays you should use general Linux API to find the volumes. The recommended way is using the [http://developer.gnome.org/gio/stable/GVolumeMonitor.html GNOME Volume Monitor] with a fallback to [http://www.freedesktop.org/wiki/Software/hal HAL] (there is an example in the [http://git.sugarlabs.org/backup/mainline/blobs/master/backup.py#line671 Backup activity]).&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strike&amp;gt;&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=79000</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=79000"/>
		<updated>2012-06-05T15:23:41Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Mount Points */ reformatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
&amp;lt;strike&amp;gt;&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data. Use the [[#External Media|external media API]] instead.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal. No access restrictions are applied currently. If activities use these external media directly, they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
Depending on the Linux distro version, the volumes appear as /mnt/*, /media/*, /run/media/$USER/*, or in other places. Sugar up to version 0.82 provided an API to access their [[#Mount Points|mount points]]. Nowadays you should use general Linux API to find the volumes. The recommended way is using the [http://developer.gnome.org/gio/stable/GVolumeMonitor.html GNOME Volume Monitor] with a fallback to [http://www.freedesktop.org/wiki/Software/hal HAL] (there is an example in the [http://git.sugarlabs.org/backup/mainline/blobs/master/backup.py#line671 Backup activity]).&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strike&amp;gt;&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78999</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78999"/>
		<updated>2012-06-05T15:18:06Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Presence */ presence service has been deprecated. strike out documentation.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
&amp;lt;strike&amp;gt;Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point&amp;lt;/strike&amp;gt; (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal. No access restrictions are applied currently. If activities use these external media directly, they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
Depending on the Linux distro version, the volumes appear as /mnt/*, /media/*, /run/media/$USER/*, or in other places. Sugar up to version 0.82 provided an API to access their [[#Mount Points|mount points]]. Nowadays you should use general Linux API to find the volumes. The recommended way is using the [http://developer.gnome.org/gio/stable/GVolumeMonitor.html GNOME Volume Monitor] with a fallback to [http://www.freedesktop.org/wiki/Software/hal HAL] (there is an example in the [http://git.sugarlabs.org/backup/mainline/blobs/master/backup.py#line671 Backup activity]).&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strike&amp;gt;&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78995</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78995"/>
		<updated>2012-06-05T15:03:24Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* External Media */ Recommend to use GIO to find volumes, not the deprecated mount points API&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
&amp;lt;strike&amp;gt;Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point&amp;lt;/strike&amp;gt; (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal. No access restrictions are applied currently. If activities use these external media directly, they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
Depending on the Linux distro version, the volumes appear as /mnt/*, /media/*, /run/media/$USER/*, or in other places. Sugar up to version 0.82 provided an API to access their [[#Mount Points|mount points]]. Nowadays you should use general Linux API to find the volumes. The recommended way is using the [http://developer.gnome.org/gio/stable/GVolumeMonitor.html GNOME Volume Monitor] with a fallback to [http://www.freedesktop.org/wiki/Software/hal HAL] (there is an example in the [http://git.sugarlabs.org/backup/mainline/blobs/master/backup.py#line671 Backup activity]).&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78991</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78991"/>
		<updated>2012-06-05T14:41:02Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Mount Points */ strike out&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
&amp;lt;strike&amp;gt;Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point&amp;lt;/strike&amp;gt; (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78990</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78990"/>
		<updated>2012-06-05T14:38:47Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Querying */ strike out mount points&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, &amp;lt;strike&amp;gt;the mountpoint of the item at key &#039;mountpoint&#039;,&amp;lt;/strike&amp;gt; and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &amp;lt;strike&amp;gt;&#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified) &amp;lt;/strike&amp;gt;&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78989</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78989"/>
		<updated>2012-06-05T14:27:29Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Focusing Objects */ mention full file path&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the &amp;quot;detail view&amp;quot; of the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file, then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
Note: since Sugar 0.84, you also can give the full path to an existing file instead of an object id. If the user resumes that file, it will be copied to the Journal first and the opened using the chosen activity. &amp;lt;i&amp;gt;This seems to be of limited usefulness and is documented here just for completeness&amp;lt;/i&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78930</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78930"/>
		<updated>2012-06-05T08:17:28Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Choosing Objects */ remove utf8 encoding - paths are just bytes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is an absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78925</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=78925"/>
		<updated>2012-06-04T21:17:19Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Choosing Objects */ object_idobject_id_or_path:s&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid:s, what_filter:s)                      # in Sugar 0.82 this had only one argument&lt;br /&gt;
&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch the following signals which get emitted when an item is chosen or the dialog is cancelled:&lt;br /&gt;
&lt;br /&gt;
 ObjectChooserResponse(chooser_id:s, object_id_or_path:s)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id:s)&lt;br /&gt;
&lt;br /&gt;
The chooser_id can be tested to see if this signal was in response to our own request. This is important if the user opens two file choosers at the same time (possibly in two different activities). If the user closes the chooser without selecting anything, the ObjectChooserCancelled signal is sent. Otherwise, the ObjectChooserResponse signal will be sent, and its object_id_or_path string argument is either an object id or a file path. To distinguish between the two cases, check if the first character is a slash (&amp;lt;tt&amp;gt;&#039;/&#039;&amp;lt;/tt&amp;gt;). If it indeed begins with a slash, then this is a utf8-encoded absolute path to a file, which can be opened directly. Otherwise, if the first character is not a slash, then object_id_or_path is an object id, which can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78611</id>
		<title>0.96/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78611"/>
		<updated>2012-05-22T10:41:34Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */ link to new features section in release notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.94/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Please do not edit unless you are part of the Sugar Release Team. Comments are welcome on the [[{{TALKPAGENAME}}|Discussion page]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.96 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sugar 0.96 is the new version of the [http://www.sugarlabs.org/ Sugar learning platform]. It was released the 30th of April 2012 (see [[0.96/Roadmap#Schedule]] for details). &lt;br /&gt;
&lt;br /&gt;
The main changes in this cycle was the introduction of the new sugar-toolkit-gtk3 which is the sugar-toolkit ported to use GTK+ 3 and Pygobject3. Currently Browse, Read, the HellowWorld activity and Abacus have been ported to the new toolkit.&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Read.png|640px]]&lt;br /&gt;
&lt;br /&gt;
The Read activity has been ported to use the new toolkit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 browse.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Besides moving to the new toolkit Browse and related components have been switching to WebKit as its back-end technology.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
&lt;br /&gt;
===Write to Journal anytime===&lt;br /&gt;
[[File:0.96 Description.png|640px]]&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Description journal.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Feature has a long history and many thinking has been going into this for a few cycles. You can now edit the description of your current activity session from within the activity. The main goal is to be able to take notes within the activity context while the activity is still running. To take notes you can reveal the description palette from a button in the activity subtoolbar, it is the same description field that is used in the Journal detail section. You can edit the description in both places, as well from within the detail view while the activity is still running, the description will be updated accordingly. &lt;br /&gt;
&lt;br /&gt;
The naming alert that prompted the learner for taking notes about the activity session when closing the activity has been removed.&lt;br /&gt;
&lt;br /&gt;
Thanks to everyone involved in this great feature, the design team and especially to Walter Bender for his constant effort over several release cycles to make this happen.&lt;br /&gt;
&lt;br /&gt;
===Global Text to Speech===&lt;br /&gt;
[[File:0.96 Text-to-speech.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The global text to speech feature gives the learner the ability to let Sugar speak out any selected text in the user interface. It can be accessed by the speech frame device which has the start/pause and stop controls. There are options in this palette to adjust the pitch and rate as well which are restored over boots. For power users the &amp;quot;alt+shift+s&amp;quot; shortcut has been added to control the speak-back.&lt;br /&gt;
&lt;br /&gt;
Thanks to Gonzalo Odiard for bringing this great Feature to us.&lt;br /&gt;
&lt;br /&gt;
===Browse===&lt;br /&gt;
[[File:0.96 Browse inline pdf.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Manuel Quiñones did a lot of work on making inline pdf viewing in Browse possible using the Evince backend. If the learner clicks on a pdf file it will open inside the Browse activity in a new tab. At the bottom of the page there are controls to navigate in the pdf, to change the view and to save the pdf to the Journal.&lt;br /&gt;
&lt;br /&gt;
===Read===&lt;br /&gt;
&#039;&#039;in progress...&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===TurtleArt===&lt;br /&gt;
[[File:TurtleArt139.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Turtle Art advanced from Version 116 to Version 139 over the past release cycle. Along with many minor bug fixes:&lt;br /&gt;
* Cairo conversion, enabling much improved graphics (anti-aliasing, rotating images and text) and an eventual port to GTK-3&lt;br /&gt;
* Overhaul of the plugin mechanism and new plugins for Physics, Nutrition, Butia, WeDo, NXT, et al.&lt;br /&gt;
* Overhaul of the help mechanism to make help more readily available&lt;br /&gt;
* New blocks for speak, mouse, and audio&lt;br /&gt;
* Improved touch support&lt;br /&gt;
Many thanks especially to the Butia team that has done stress-testing of the plug-in mechanism and as a result led to many improvements.&lt;br /&gt;
&lt;br /&gt;
===Measure===&lt;br /&gt;
[[File:Measure-37.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Measure underwent a major refactoring to enable stereo capture of analog audio and digital data.&lt;br /&gt;
&lt;br /&gt;
===Etoys===&lt;br /&gt;
[[File:Etoys5-Home.png|640px|border]]&lt;br /&gt;
&lt;br /&gt;
This Sugar release includes Etoys 5.0, which has many new features, including:&lt;br /&gt;
&lt;br /&gt;
* a “single-step” feature in the scriptor&lt;br /&gt;
* a scriptable calendar&lt;br /&gt;
* a scriptable “sector” object, allowing you to create slices of a pie of any angle&lt;br /&gt;
* a “key press” object, which reports whether, and for how long, a specific key is pressed&lt;br /&gt;
* “attached” watchers, which always appear near the object they watch&lt;br /&gt;
* number lines, and a “graph paper” tool to make graph-paper-like backgrounds&lt;br /&gt;
* new languages: Armenian, Dansk, Papiamentu, Polish&lt;br /&gt;
&lt;br /&gt;
See [http://squeakland.org/download/releaseNotes.jsp#features Etoys Release Notes] for further details.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.96 developer platform:&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
The most important change is that the GTK+ 2 based sugar-toolkit has been deprecated. Newly written activities should use sugar-toolkit-gtk3, which is based on GTK+ 3 and Pygobject3, now. There will be only bug fixes being available in the future for the old toolkit no new features will be made available for it and it will probably go away at one point completely. Detailed guidelines for porting existing activities can be found at [[Features/GTK3/Porting]].&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
The Keep button has been removed completely from the API later; please adjust existing activities accordingly.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
In sugar-toolkit-gtk3 API that has been deprecated for several development cycles have been removed:&lt;br /&gt;
&lt;br /&gt;
* Remove support for the old deprecated toolbar &lt;br /&gt;
** removed deprecated imports from the activity module, use the widgets module instead&lt;br /&gt;
** removed the ActivityToolbox class&lt;br /&gt;
** removed the Stop button from the ActivityToolbar&lt;br /&gt;
** removed set_toolbar/get_toolbar API from the window module&lt;br /&gt;
*Datastore: remove deprecated API&lt;br /&gt;
*ObjectChooser: remove deprecated parameters&lt;br /&gt;
** The objectchooser had the &#039;title&#039;, &#039;flags&#039; and &#039;buttons&#039; parameters deprecated for a long time, remove them now completely. The only parameters allowed are now the &#039;parent&#039; and the &#039;what_filter&#039;.&lt;br /&gt;
* Bundlebuilder: remove deprecated bundle_name argument&lt;br /&gt;
* Activity: remove deprecated _shared_activity member&lt;br /&gt;
* ActivityBundle: clean from deprecated code&lt;br /&gt;
** removed deprecated mime type &#039;application/vnd.olpc-x-sugar&#039;&lt;br /&gt;
** activity.info file: removed deprecated field &#039;service_name&#039; use &#039;bundle_id&#039; instead&lt;br /&gt;
** activity.info file: removed deprecated field &#039;class&#039; use &#039;exec&#039; instead&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
* the sugar-toolkit-gtk3 repository has been added&lt;br /&gt;
* the Browse activity depend webkitgtk3 instead of xulrunner and hulahop, the hulahop module has been deprecated&lt;br /&gt;
* etoys 5.0 needs a new Squeak VM plugin for camera access. The [http://lists.squeak.org/pipermail/vm-dev/2012-May/010646.html source] has been submitted to the vm developers but is not in the [http://squeakvm.org/unix/ latest release] (4.4.7) yet&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
[[File:0.96 arabic sugar.png|640px|Sugar localized in Kinyarwanda]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Kinyarwanda.png|640px|Sugar localized in Arabic]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the Sucrose 0.96 release, 16 languages are 100% complete (with respect to the core Glucose module).&lt;br /&gt;
&lt;br /&gt;
Armenian, Chinese (China), Chinese (Taiwan), Danish, Dutch, English (United Kingdom), English (US), French, German, Huastec (Tének), Nepali, Polish, Portuguese, Sinhala, Spanish, Thai.	&lt;br /&gt;
&lt;br /&gt;
An additional 8 languages are greater than 80% complete.&lt;br /&gt;
&lt;br /&gt;
Arabic, Bengali, Greek, Hindi, Japanese, Kinyarwanda, Tamil, Vietnamese.&lt;br /&gt;
&lt;br /&gt;
With some localization done on a total of 86 languages.&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Activities that has been ported to sugar-toolkit-gtk3 will not run on older Sugar versions where the new toolkit is not available. Which means latest Browse and Read will not run on Sugar versions &amp;lt; 0.96. This is reflected in the activity providing backend ASLO where the activities are marked 0.96 only.&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package Sugar for your favorite distribution or just want to examine Sugar&#039;s lovely code here are the released bundles. If you are interested in the full changelog you can use the [http://git.sugarlabs.org/ Sugar git repositories].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.96.1.tar.bz2 sugar 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.96.0.tar.bz2 sugar-datastore 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.96.1.tar.bz2 sugar-toolkit 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit-gtk3/sugar-toolkit-gtk3-0.96.1.tar.bz2 sugar-toolkit-gtk3 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.96.0.tar.bz2 sugar-base 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.96.2.tar.bz2 sugar-artwork 0.96.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-5.0.2403.tar.gz etoys 5.0.2403]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-46.tar.bz2 Pippy 46]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-137.tar.bz2 Browse 137]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-40.tar.bz2 Calculate 40]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-76.tar.bz2 Chat 76]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-139.tar.bz2 TurtleArt 139]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-23.tar.bz2 Jukebox 23]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-28.tar.bz2 Log 28]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-20.tar.bz2 ImageViewer 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-79.tar.bz2 Write 79]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Terminal/Terminal-36.tar.bz2 Terminal 36]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Read/Read-99.tar.bz2 Read 99]&lt;br /&gt;
&lt;br /&gt;
== How to contribute with testing ==&lt;br /&gt;
Sugar 0.96 has been released. We are still stabilizing the areas that have seen major changes like the new stugar-toolkit-gtk3 the new GTK+ 3 Sugar theme and the Browse activity that has been ported to use Webkit. It is very important to get feedback from and that you report the bugs you find. The order of stability depends among other things as well on &#039;&#039;&#039;you&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
If you find bugs please report them into the [http://bugs.sugarlabs.org/ Sugar Labs bug tracker] indicating the 0.96.x version in the ticket version field. If you have hardware from OLPC you can use the [http://build.laptop.org/12.1.0/  12.1.0 builds] for the i686 architecture (XO 1 and XO 1.5) and the ARM architecture (XO 1.75). Those builds include the latest Sugar 0.96.x. Hardware specific bugs especially with the new 1.75 hardware please report at the [http://dev.laptop.org/ OLPC bug tracker]. The current development version is as well available in [http://fedoraproject.org/wiki/Releases/17 Fedora 17] and [[Development_Team/Jhbuild |sugar-jhbuild]] (sugar* master branches).&lt;br /&gt;
&lt;br /&gt;
==Credits==&lt;br /&gt;
This cycle we want to espacially thank the contributors to the GTK+ 3/pygobject3 port of the toolkit! All the attendees of the [[Marketing_Team/Events/Gtk3_Hackfest_2011]] in Praha and the Rosario meetup our warmest &amp;quot;thank you&amp;quot;. Kudos go to the Palette people!&lt;br /&gt;
&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes and do review other&#039;s patches,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing a Sugar version to test with during the development cycle,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;br /&gt;
&lt;br /&gt;
== Looking forward to 0.98==&lt;br /&gt;
In the 0.98 development cycle the porting of the Shell to GTK+ 3 and pygobject3 is a major task. Furthermore the remaining bugs in the new sugar-toolkit-gtk3 should be fixed. We encourage activity developers to port their activity to the new toolkit and GTK+ 3 and pygobject3.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78610</id>
		<title>0.96/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78610"/>
		<updated>2012-05-22T10:37:31Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */ Added screenshots&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.94/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Please do not edit unless you are part of the Sugar Release Team. Comments are welcome on the [[{{TALKPAGENAME}}|Discussion page]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.96 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sugar 0.96 is the new version of the [http://www.sugarlabs.org/ Sugar learning platform]. It was released the 30th of April 2012 (see [[0.96/Roadmap#Schedule]] for details). &lt;br /&gt;
&lt;br /&gt;
The main changes in this cycle was the introduction of the new sugar-toolkit-gtk3 which is the sugar-toolkit ported to use GTK+ 3 and Pygobject3. Currently Browse, Read, the HellowWorld activity and Abacus have been ported to the new toolkit.&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Read.png|640px]]&lt;br /&gt;
&lt;br /&gt;
The Read activity has been ported to use the new toolkit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 browse.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Besides moving to the new toolkit Browse and related components have been switching to WebKit as its back-end technology.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
&lt;br /&gt;
===Write to Journal anytime===&lt;br /&gt;
[[File:0.96 Description.png|640px]]&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Description journal.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Feature has a long history and many thinking has been going into this for a few cycles. You can now edit the description of your current activity session from within the activity. The main goal is to be able to take notes within the activity context while the activity is still running. To take notes you can reveal the description palette from a button in the activity subtoolbar, it is the same description field that is used in the Journal detail section. You can edit the description in both places, as well from within the detail view while the activity is still running, the description will be updated accordingly. &lt;br /&gt;
&lt;br /&gt;
The naming alert that prompted the learner for taking notes about the activity session when closing the activity has been removed.&lt;br /&gt;
&lt;br /&gt;
Thanks to everyone involved in this great feature, the design team and especially to Walter Bender for his constant effort over several release cycles to make this happen.&lt;br /&gt;
&lt;br /&gt;
===Global Text to Speech===&lt;br /&gt;
[[File:0.96 Text-to-speech.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The global text to speech feature gives the learner the ability to let Sugar speak out any selected text in the user interface. It can be accessed by the speech frame device which has the start/pause and stop controls. There are options in this palette to adjust the pitch and rate as well which are restored over boots. For power users the &amp;quot;alt+shift+s&amp;quot; shortcut has been added to control the speak-back.&lt;br /&gt;
&lt;br /&gt;
Thanks to Gonzalo Odiard for bringing this great Feature to us.&lt;br /&gt;
&lt;br /&gt;
===Browse===&lt;br /&gt;
[[File:0.96 Browse inline pdf.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Manuel Quiñones did a lot of work on making inline pdf viewing in Browse possible using the Evince backend. If the learner clicks on a pdf file it will open inside the Browse activity in a new tab. At the bottom of the page there are controls to navigate in the pdf, to change the view and to save the pdf to the Journal.&lt;br /&gt;
&lt;br /&gt;
===Read===&lt;br /&gt;
&#039;&#039;in progress...&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===TurtleArt===&lt;br /&gt;
[[File:TurtleArt139.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Turtle Art advanced from Version 116 to Version 139 over the past release cycle. Along with many minor bug fixes:&lt;br /&gt;
* Cairo conversion, enabling much improved graphics (anti-aliasing, rotating images and text) and an eventual port to GTK-3&lt;br /&gt;
* Overhaul of the plugin mechanism and new plugins for Physics, Nutrition, Butia, WeDo, NXT, et al.&lt;br /&gt;
* Overhaul of the help mechanism to make help more readily available&lt;br /&gt;
* New blocks for speak, mouse, and audio&lt;br /&gt;
* Improved touch support&lt;br /&gt;
Many thanks especially to the Butia team that has done stress-testing of the plug-in mechanism and as a result led to many improvements.&lt;br /&gt;
&lt;br /&gt;
===Measure===&lt;br /&gt;
[[File:Measure-37.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Measure underwent a major refactoring to enable stereo capture of analog audio and digital data.&lt;br /&gt;
&lt;br /&gt;
===Etoys===&lt;br /&gt;
[[File:Etoys5-Home.png|640px|border]]&lt;br /&gt;
&lt;br /&gt;
This Sugar release includes Etoys 5.0, which has many new features, including:&lt;br /&gt;
&lt;br /&gt;
* a “single-step” feature in the scriptor&lt;br /&gt;
* a scriptable calendar&lt;br /&gt;
* a scriptable “sector” object, allowing you to create slices of a pie of any angle&lt;br /&gt;
* a “key press” object, which reports whether, and for how long, a specific key is pressed&lt;br /&gt;
* “attached” watchers, which always appear near the object they watch&lt;br /&gt;
* number lines, and a “graph paper” tool to make graph-paper-like backgrounds&lt;br /&gt;
* new languages: Armenian, Dansk, Papiamentu, Polish&lt;br /&gt;
&lt;br /&gt;
See [http://squeakland.org/download/releaseNotes.jsp Etoys Release Notes] for further details.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.96 developer platform:&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
The most important change is that the GTK+ 2 based sugar-toolkit has been deprecated. Newly written activities should use sugar-toolkit-gtk3, which is based on GTK+ 3 and Pygobject3, now. There will be only bug fixes being available in the future for the old toolkit no new features will be made available for it and it will probably go away at one point completely. Detailed guidelines for porting existing activities can be found at [[Features/GTK3/Porting]].&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
The Keep button has been removed completely from the API later; please adjust existing activities accordingly.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
In sugar-toolkit-gtk3 API that has been deprecated for several development cycles have been removed:&lt;br /&gt;
&lt;br /&gt;
* Remove support for the old deprecated toolbar &lt;br /&gt;
** removed deprecated imports from the activity module, use the widgets module instead&lt;br /&gt;
** removed the ActivityToolbox class&lt;br /&gt;
** removed the Stop button from the ActivityToolbar&lt;br /&gt;
** removed set_toolbar/get_toolbar API from the window module&lt;br /&gt;
*Datastore: remove deprecated API&lt;br /&gt;
*ObjectChooser: remove deprecated parameters&lt;br /&gt;
** The objectchooser had the &#039;title&#039;, &#039;flags&#039; and &#039;buttons&#039; parameters deprecated for a long time, remove them now completely. The only parameters allowed are now the &#039;parent&#039; and the &#039;what_filter&#039;.&lt;br /&gt;
* Bundlebuilder: remove deprecated bundle_name argument&lt;br /&gt;
* Activity: remove deprecated _shared_activity member&lt;br /&gt;
* ActivityBundle: clean from deprecated code&lt;br /&gt;
** removed deprecated mime type &#039;application/vnd.olpc-x-sugar&#039;&lt;br /&gt;
** activity.info file: removed deprecated field &#039;service_name&#039; use &#039;bundle_id&#039; instead&lt;br /&gt;
** activity.info file: removed deprecated field &#039;class&#039; use &#039;exec&#039; instead&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
* the sugar-toolkit-gtk3 repository has been added&lt;br /&gt;
* the Browse activity depend webkitgtk3 instead of xulrunner and hulahop, the hulahop module has been deprecated&lt;br /&gt;
* etoys 5.0 needs a new Squeak VM plugin for camera access. The [http://lists.squeak.org/pipermail/vm-dev/2012-May/010646.html source] has been submitted to the vm developers but is not in the [http://squeakvm.org/unix/ latest release] (4.4.7) yet&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
[[File:0.96 arabic sugar.png|640px|Sugar localized in Kinyarwanda]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Kinyarwanda.png|640px|Sugar localized in Arabic]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the Sucrose 0.96 release, 16 languages are 100% complete (with respect to the core Glucose module).&lt;br /&gt;
&lt;br /&gt;
Armenian, Chinese (China), Chinese (Taiwan), Danish, Dutch, English (United Kingdom), English (US), French, German, Huastec (Tének), Nepali, Polish, Portuguese, Sinhala, Spanish, Thai.	&lt;br /&gt;
&lt;br /&gt;
An additional 8 languages are greater than 80% complete.&lt;br /&gt;
&lt;br /&gt;
Arabic, Bengali, Greek, Hindi, Japanese, Kinyarwanda, Tamil, Vietnamese.&lt;br /&gt;
&lt;br /&gt;
With some localization done on a total of 86 languages.&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Activities that has been ported to sugar-toolkit-gtk3 will not run on older Sugar versions where the new toolkit is not available. Which means latest Browse and Read will not run on Sugar versions &amp;lt; 0.96. This is reflected in the activity providing backend ASLO where the activities are marked 0.96 only.&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package Sugar for your favorite distribution or just want to examine Sugar&#039;s lovely code here are the released bundles. If you are interested in the full changelog you can use the [http://git.sugarlabs.org/ Sugar git repositories].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.96.1.tar.bz2 sugar 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.96.0.tar.bz2 sugar-datastore 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.96.1.tar.bz2 sugar-toolkit 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit-gtk3/sugar-toolkit-gtk3-0.96.1.tar.bz2 sugar-toolkit-gtk3 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.96.0.tar.bz2 sugar-base 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.96.2.tar.bz2 sugar-artwork 0.96.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-5.0.2403.tar.gz etoys 5.0.2403]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-46.tar.bz2 Pippy 46]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-137.tar.bz2 Browse 137]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-40.tar.bz2 Calculate 40]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-76.tar.bz2 Chat 76]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-139.tar.bz2 TurtleArt 139]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-23.tar.bz2 Jukebox 23]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-28.tar.bz2 Log 28]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-20.tar.bz2 ImageViewer 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-79.tar.bz2 Write 79]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Terminal/Terminal-36.tar.bz2 Terminal 36]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Read/Read-99.tar.bz2 Read 99]&lt;br /&gt;
&lt;br /&gt;
== How to contribute with testing ==&lt;br /&gt;
Sugar 0.96 has been released. We are still stabilizing the areas that have seen major changes like the new stugar-toolkit-gtk3 the new GTK+ 3 Sugar theme and the Browse activity that has been ported to use Webkit. It is very important to get feedback from and that you report the bugs you find. The order of stability depends among other things as well on &#039;&#039;&#039;you&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
If you find bugs please report them into the [http://bugs.sugarlabs.org/ Sugar Labs bug tracker] indicating the 0.96.x version in the ticket version field. If you have hardware from OLPC you can use the [http://build.laptop.org/12.1.0/  12.1.0 builds] for the i686 architecture (XO 1 and XO 1.5) and the ARM architecture (XO 1.75). Those builds include the latest Sugar 0.96.x. Hardware specific bugs especially with the new 1.75 hardware please report at the [http://dev.laptop.org/ OLPC bug tracker]. The current development version is as well available in [http://fedoraproject.org/wiki/Releases/17 Fedora 17] and [[Development_Team/Jhbuild |sugar-jhbuild]] (sugar* master branches).&lt;br /&gt;
&lt;br /&gt;
==Credits==&lt;br /&gt;
This cycle we want to espacially thank the contributors to the GTK+ 3/pygobject3 port of the toolkit! All the attendees of the [[Marketing_Team/Events/Gtk3_Hackfest_2011]] in Praha and the Rosario meetup our warmest &amp;quot;thank you&amp;quot;. Kudos go to the Palette people!&lt;br /&gt;
&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes and do review other&#039;s patches,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing a Sugar version to test with during the development cycle,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;br /&gt;
&lt;br /&gt;
== Looking forward to 0.98==&lt;br /&gt;
In the 0.98 development cycle the porting of the Shell to GTK+ 3 and pygobject3 is a major task. Furthermore the remaining bugs in the new sugar-toolkit-gtk3 should be fixed. We encourage activity developers to port their activity to the new toolkit and GTK+ 3 and pygobject3.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Etoys5-Home.png&amp;diff=78609</id>
		<title>File:Etoys5-Home.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Etoys5-Home.png&amp;diff=78609"/>
		<updated>2012-05-22T10:34:09Z</updated>

		<summary type="html">&lt;p&gt;Bert: Screenshot of Etoys 5 with pen tracing enabled for little red car&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot of Etoys 5 with pen tracing enabled for little red car&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78608</id>
		<title>0.96/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78608"/>
		<updated>2012-05-22T10:17:10Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* What&amp;#039;s new for packagers */ need new Squeak VM&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.94/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Please do not edit unless you are part of the Sugar Release Team. Comments are welcome on the [[{{TALKPAGENAME}}|Discussion page]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.96 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sugar 0.96 is the new version of the [http://www.sugarlabs.org/ Sugar learning platform]. It was released the 30th of April 2012 (see [[0.96/Roadmap#Schedule]] for details). &lt;br /&gt;
&lt;br /&gt;
The main changes in this cycle was the introduction of the new sugar-toolkit-gtk3 which is the sugar-toolkit ported to use GTK+ 3 and Pygobject3. Currently Browse, Read, the HellowWorld activity and Abacus have been ported to the new toolkit.&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Read.png|640px]]&lt;br /&gt;
&lt;br /&gt;
The Read activity has been ported to use the new toolkit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 browse.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Besides moving to the new toolkit Browse and related components have been switching to WebKit as its back-end technology.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
&lt;br /&gt;
===Write to Journal anytime===&lt;br /&gt;
[[File:0.96 Description.png|640px]]&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Description journal.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Feature has a long history and many thinking has been going into this for a few cycles. You can now edit the description of your current activity session from within the activity. The main goal is to be able to take notes within the activity context while the activity is still running. To take notes you can reveal the description palette from a button in the activity subtoolbar, it is the same description field that is used in the Journal detail section. You can edit the description in both places, as well from within the detail view while the activity is still running, the description will be updated accordingly. &lt;br /&gt;
&lt;br /&gt;
The naming alert that prompted the learner for taking notes about the activity session when closing the activity has been removed.&lt;br /&gt;
&lt;br /&gt;
Thanks to everyone involved in this great feature, the design team and especially to Walter Bender for his constant effort over several release cycles to make this happen.&lt;br /&gt;
&lt;br /&gt;
===Global Text to Speech===&lt;br /&gt;
[[File:0.96 Text-to-speech.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The global text to speech feature gives the learner the ability to let Sugar speak out any selected text in the user interface. It can be accessed by the speech frame device which has the start/pause and stop controls. There are options in this palette to adjust the pitch and rate as well which are restored over boots. For power users the &amp;quot;alt+shift+s&amp;quot; shortcut has been added to control the speak-back.&lt;br /&gt;
&lt;br /&gt;
Thanks to Gonzalo Odiard for bringing this great Feature to us.&lt;br /&gt;
&lt;br /&gt;
===Browse===&lt;br /&gt;
[[File:0.96 Browse inline pdf.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Manuel Quiñones did a lot of work on making inline pdf viewing in Browse possible using the Evince backend. If the learner clicks on a pdf file it will open inside the Browse activity in a new tab. At the bottom of the page there are controls to navigate in the pdf, to change the view and to save the pdf to the Journal.&lt;br /&gt;
&lt;br /&gt;
===Read===&lt;br /&gt;
&#039;&#039;in progress...&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===TurtleArt===&lt;br /&gt;
[[File:TurtleArt139.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Turtle Art advanced from Version 116 to Version 139 over the past release cycle. Along with many minor bug fixes:&lt;br /&gt;
* Cairo conversion, enabling much improved graphics (anti-aliasing, rotating images and text) and an eventual port to GTK-3&lt;br /&gt;
* Overhaul of the plugin mechanism and new plugins for Physics, Nutrition, Butia, WeDo, NXT, et al.&lt;br /&gt;
* Overhaul of the help mechanism to make help more readily available&lt;br /&gt;
* New blocks for speak, mouse, and audio&lt;br /&gt;
* Improved touch support&lt;br /&gt;
Many thanks especially to the Butia team that has done stress-testing of the plug-in mechanism and as a result led to many improvements.&lt;br /&gt;
&lt;br /&gt;
===Measure===&lt;br /&gt;
[[File:Measure-37.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Measure underwent a major refactoring to enable stereo capture of analog audio and digital data.&lt;br /&gt;
&lt;br /&gt;
===Etoys===&lt;br /&gt;
This Sugar release includes Etoys 5.0, which has many new features, including:&lt;br /&gt;
&lt;br /&gt;
* a “single-step” feature in the scriptor&lt;br /&gt;
* a scriptable calendar&lt;br /&gt;
* a scriptable “sector” object, allowing you to create slices of a pie of any angle&lt;br /&gt;
* a “key press” object, which reports whether, and for how long, a specific key is pressed&lt;br /&gt;
* “attached” watchers, which always appear near the object they watch&lt;br /&gt;
* number lines, and a “graph paper” tool to make graph-paper-like backgrounds&lt;br /&gt;
* new languages: Armenian, Dansk, Papiamentu, Polish&lt;br /&gt;
&lt;br /&gt;
See [http://squeakland.org/download/releaseNotes.jsp Etoys Release Notes] for further details.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.96 developer platform:&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
The most important change is that the GTK+ 2 based sugar-toolkit has been deprecated. Newly written activities should use sugar-toolkit-gtk3, which is based on GTK+ 3 and Pygobject3, now. There will be only bug fixes being available in the future for the old toolkit no new features will be made available for it and it will probably go away at one point completely. Detailed guidelines for porting existing activities can be found at [[Features/GTK3/Porting]].&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
The Keep button has been removed completely from the API later; please adjust existing activities accordingly.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
In sugar-toolkit-gtk3 API that has been deprecated for several development cycles have been removed:&lt;br /&gt;
&lt;br /&gt;
* Remove support for the old deprecated toolbar &lt;br /&gt;
** removed deprecated imports from the activity module, use the widgets module instead&lt;br /&gt;
** removed the ActivityToolbox class&lt;br /&gt;
** removed the Stop button from the ActivityToolbar&lt;br /&gt;
** removed set_toolbar/get_toolbar API from the window module&lt;br /&gt;
*Datastore: remove deprecated API&lt;br /&gt;
*ObjectChooser: remove deprecated parameters&lt;br /&gt;
** The objectchooser had the &#039;title&#039;, &#039;flags&#039; and &#039;buttons&#039; parameters deprecated for a long time, remove them now completely. The only parameters allowed are now the &#039;parent&#039; and the &#039;what_filter&#039;.&lt;br /&gt;
* Bundlebuilder: remove deprecated bundle_name argument&lt;br /&gt;
* Activity: remove deprecated _shared_activity member&lt;br /&gt;
* ActivityBundle: clean from deprecated code&lt;br /&gt;
** removed deprecated mime type &#039;application/vnd.olpc-x-sugar&#039;&lt;br /&gt;
** activity.info file: removed deprecated field &#039;service_name&#039; use &#039;bundle_id&#039; instead&lt;br /&gt;
** activity.info file: removed deprecated field &#039;class&#039; use &#039;exec&#039; instead&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
* the sugar-toolkit-gtk3 repository has been added&lt;br /&gt;
* the Browse activity depend webkitgtk3 instead of xulrunner and hulahop, the hulahop module has been deprecated&lt;br /&gt;
* etoys 5.0 needs a new Squeak VM plugin for camera access. The [http://lists.squeak.org/pipermail/vm-dev/2012-May/010646.html source] has been submitted to the vm developers but is not in the [http://squeakvm.org/unix/ latest release] (4.4.7) yet&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
[[File:0.96 arabic sugar.png|640px|Sugar localized in Kinyarwanda]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Kinyarwanda.png|640px|Sugar localized in Arabic]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the Sucrose 0.96 release, 16 languages are 100% complete (with respect to the core Glucose module).&lt;br /&gt;
&lt;br /&gt;
Armenian, Chinese (China), Chinese (Taiwan), Danish, Dutch, English (United Kingdom), English (US), French, German, Huastec (Tének), Nepali, Polish, Portuguese, Sinhala, Spanish, Thai.	&lt;br /&gt;
&lt;br /&gt;
An additional 8 languages are greater than 80% complete.&lt;br /&gt;
&lt;br /&gt;
Arabic, Bengali, Greek, Hindi, Japanese, Kinyarwanda, Tamil, Vietnamese.&lt;br /&gt;
&lt;br /&gt;
With some localization done on a total of 86 languages.&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Activities that has been ported to sugar-toolkit-gtk3 will not run on older Sugar versions where the new toolkit is not available. Which means latest Browse and Read will not run on Sugar versions &amp;lt; 0.96. This is reflected in the activity providing backend ASLO where the activities are marked 0.96 only.&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package Sugar for your favorite distribution or just want to examine Sugar&#039;s lovely code here are the released bundles. If you are interested in the full changelog you can use the [http://git.sugarlabs.org/ Sugar git repositories].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.96.1.tar.bz2 sugar 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.96.0.tar.bz2 sugar-datastore 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.96.1.tar.bz2 sugar-toolkit 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit-gtk3/sugar-toolkit-gtk3-0.96.1.tar.bz2 sugar-toolkit-gtk3 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.96.0.tar.bz2 sugar-base 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.96.2.tar.bz2 sugar-artwork 0.96.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-5.0.2403.tar.gz etoys 5.0.2403]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-46.tar.bz2 Pippy 46]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-137.tar.bz2 Browse 137]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-40.tar.bz2 Calculate 40]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-76.tar.bz2 Chat 76]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-139.tar.bz2 TurtleArt 139]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-23.tar.bz2 Jukebox 23]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-28.tar.bz2 Log 28]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-20.tar.bz2 ImageViewer 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-79.tar.bz2 Write 79]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Terminal/Terminal-36.tar.bz2 Terminal 36]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Read/Read-99.tar.bz2 Read 99]&lt;br /&gt;
&lt;br /&gt;
== How to contribute with testing ==&lt;br /&gt;
Sugar 0.96 has been released. We are still stabilizing the areas that have seen major changes like the new stugar-toolkit-gtk3 the new GTK+ 3 Sugar theme and the Browse activity that has been ported to use Webkit. It is very important to get feedback from and that you report the bugs you find. The order of stability depends among other things as well on &#039;&#039;&#039;you&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
If you find bugs please report them into the [http://bugs.sugarlabs.org/ Sugar Labs bug tracker] indicating the 0.96.x version in the ticket version field. If you have hardware from OLPC you can use the [http://build.laptop.org/12.1.0/  12.1.0 builds] for the i686 architecture (XO 1 and XO 1.5) and the ARM architecture (XO 1.75). Those builds include the latest Sugar 0.96.x. Hardware specific bugs especially with the new 1.75 hardware please report at the [http://dev.laptop.org/ OLPC bug tracker]. The current development version is as well available in [http://fedoraproject.org/wiki/Releases/17 Fedora 17] and [[Development_Team/Jhbuild |sugar-jhbuild]] (sugar* master branches).&lt;br /&gt;
&lt;br /&gt;
==Credits==&lt;br /&gt;
This cycle we want to espacially thank the contributors to the GTK+ 3/pygobject3 port of the toolkit! All the attendees of the [[Marketing_Team/Events/Gtk3_Hackfest_2011]] in Praha and the Rosario meetup our warmest &amp;quot;thank you&amp;quot;. Kudos go to the Palette people!&lt;br /&gt;
&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes and do review other&#039;s patches,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing a Sugar version to test with during the development cycle,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;br /&gt;
&lt;br /&gt;
== Looking forward to 0.98==&lt;br /&gt;
In the 0.98 development cycle the porting of the Shell to GTK+ 3 and pygobject3 is a major task. Furthermore the remaining bugs in the new sugar-toolkit-gtk3 should be fixed. We encourage activity developers to port their activity to the new toolkit and GTK+ 3 and pygobject3.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78607</id>
		<title>0.96/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.96/Notes&amp;diff=78607"/>
		<updated>2012-05-22T10:11:50Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */ Added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.94/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Please do not edit unless you are part of the Sugar Release Team. Comments are welcome on the [[{{TALKPAGENAME}}|Discussion page]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.96 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sugar 0.96 is the new version of the [http://www.sugarlabs.org/ Sugar learning platform]. It was released the 30th of April 2012 (see [[0.96/Roadmap#Schedule]] for details). &lt;br /&gt;
&lt;br /&gt;
The main changes in this cycle was the introduction of the new sugar-toolkit-gtk3 which is the sugar-toolkit ported to use GTK+ 3 and Pygobject3. Currently Browse, Read, the HellowWorld activity and Abacus have been ported to the new toolkit.&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Read.png|640px]]&lt;br /&gt;
&lt;br /&gt;
The Read activity has been ported to use the new toolkit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 browse.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Besides moving to the new toolkit Browse and related components have been switching to WebKit as its back-end technology.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
&lt;br /&gt;
===Write to Journal anytime===&lt;br /&gt;
[[File:0.96 Description.png|640px]]&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Description journal.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Feature has a long history and many thinking has been going into this for a few cycles. You can now edit the description of your current activity session from within the activity. The main goal is to be able to take notes within the activity context while the activity is still running. To take notes you can reveal the description palette from a button in the activity subtoolbar, it is the same description field that is used in the Journal detail section. You can edit the description in both places, as well from within the detail view while the activity is still running, the description will be updated accordingly. &lt;br /&gt;
&lt;br /&gt;
The naming alert that prompted the learner for taking notes about the activity session when closing the activity has been removed.&lt;br /&gt;
&lt;br /&gt;
Thanks to everyone involved in this great feature, the design team and especially to Walter Bender for his constant effort over several release cycles to make this happen.&lt;br /&gt;
&lt;br /&gt;
===Global Text to Speech===&lt;br /&gt;
[[File:0.96 Text-to-speech.png|640px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The global text to speech feature gives the learner the ability to let Sugar speak out any selected text in the user interface. It can be accessed by the speech frame device which has the start/pause and stop controls. There are options in this palette to adjust the pitch and rate as well which are restored over boots. For power users the &amp;quot;alt+shift+s&amp;quot; shortcut has been added to control the speak-back.&lt;br /&gt;
&lt;br /&gt;
Thanks to Gonzalo Odiard for bringing this great Feature to us.&lt;br /&gt;
&lt;br /&gt;
===Browse===&lt;br /&gt;
[[File:0.96 Browse inline pdf.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Manuel Quiñones did a lot of work on making inline pdf viewing in Browse possible using the Evince backend. If the learner clicks on a pdf file it will open inside the Browse activity in a new tab. At the bottom of the page there are controls to navigate in the pdf, to change the view and to save the pdf to the Journal.&lt;br /&gt;
&lt;br /&gt;
===Read===&lt;br /&gt;
&#039;&#039;in progress...&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===TurtleArt===&lt;br /&gt;
[[File:TurtleArt139.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Turtle Art advanced from Version 116 to Version 139 over the past release cycle. Along with many minor bug fixes:&lt;br /&gt;
* Cairo conversion, enabling much improved graphics (anti-aliasing, rotating images and text) and an eventual port to GTK-3&lt;br /&gt;
* Overhaul of the plugin mechanism and new plugins for Physics, Nutrition, Butia, WeDo, NXT, et al.&lt;br /&gt;
* Overhaul of the help mechanism to make help more readily available&lt;br /&gt;
* New blocks for speak, mouse, and audio&lt;br /&gt;
* Improved touch support&lt;br /&gt;
Many thanks especially to the Butia team that has done stress-testing of the plug-in mechanism and as a result led to many improvements.&lt;br /&gt;
&lt;br /&gt;
===Measure===&lt;br /&gt;
[[File:Measure-37.png|640px]]&lt;br /&gt;
&lt;br /&gt;
Measure underwent a major refactoring to enable stereo capture of analog audio and digital data.&lt;br /&gt;
&lt;br /&gt;
===Etoys===&lt;br /&gt;
This Sugar release includes Etoys 5.0, which has many new features, including:&lt;br /&gt;
&lt;br /&gt;
* a “single-step” feature in the scriptor&lt;br /&gt;
* a scriptable calendar&lt;br /&gt;
* a scriptable “sector” object, allowing you to create slices of a pie of any angle&lt;br /&gt;
* a “key press” object, which reports whether, and for how long, a specific key is pressed&lt;br /&gt;
* “attached” watchers, which always appear near the object they watch&lt;br /&gt;
* number lines, and a “graph paper” tool to make graph-paper-like backgrounds&lt;br /&gt;
* new languages: Armenian, Dansk, Papiamentu, Polish&lt;br /&gt;
&lt;br /&gt;
See [http://squeakland.org/download/releaseNotes.jsp Etoys Release Notes] for further details.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.96 developer platform:&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
The most important change is that the GTK+ 2 based sugar-toolkit has been deprecated. Newly written activities should use sugar-toolkit-gtk3, which is based on GTK+ 3 and Pygobject3, now. There will be only bug fixes being available in the future for the old toolkit no new features will be made available for it and it will probably go away at one point completely. Detailed guidelines for porting existing activities can be found at [[Features/GTK3/Porting]].&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
The Keep button has been removed completely from the API later; please adjust existing activities accordingly.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
In sugar-toolkit-gtk3 API that has been deprecated for several development cycles have been removed:&lt;br /&gt;
&lt;br /&gt;
* Remove support for the old deprecated toolbar &lt;br /&gt;
** removed deprecated imports from the activity module, use the widgets module instead&lt;br /&gt;
** removed the ActivityToolbox class&lt;br /&gt;
** removed the Stop button from the ActivityToolbar&lt;br /&gt;
** removed set_toolbar/get_toolbar API from the window module&lt;br /&gt;
*Datastore: remove deprecated API&lt;br /&gt;
*ObjectChooser: remove deprecated parameters&lt;br /&gt;
** The objectchooser had the &#039;title&#039;, &#039;flags&#039; and &#039;buttons&#039; parameters deprecated for a long time, remove them now completely. The only parameters allowed are now the &#039;parent&#039; and the &#039;what_filter&#039;.&lt;br /&gt;
* Bundlebuilder: remove deprecated bundle_name argument&lt;br /&gt;
* Activity: remove deprecated _shared_activity member&lt;br /&gt;
* ActivityBundle: clean from deprecated code&lt;br /&gt;
** removed deprecated mime type &#039;application/vnd.olpc-x-sugar&#039;&lt;br /&gt;
** activity.info file: removed deprecated field &#039;service_name&#039; use &#039;bundle_id&#039; instead&lt;br /&gt;
** activity.info file: removed deprecated field &#039;class&#039; use &#039;exec&#039; instead&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
* the sugar-toolkit-gtk3 repository has been added&lt;br /&gt;
* the Browse activity depend webkitgtk3 instead of xulrunner and hulahop, the hulahop module has been deprecated&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
[[File:0.96 arabic sugar.png|640px|Sugar localized in Kinyarwanda]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:0.96 Kinyarwanda.png|640px|Sugar localized in Arabic]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the Sucrose 0.96 release, 16 languages are 100% complete (with respect to the core Glucose module).&lt;br /&gt;
&lt;br /&gt;
Armenian, Chinese (China), Chinese (Taiwan), Danish, Dutch, English (United Kingdom), English (US), French, German, Huastec (Tének), Nepali, Polish, Portuguese, Sinhala, Spanish, Thai.	&lt;br /&gt;
&lt;br /&gt;
An additional 8 languages are greater than 80% complete.&lt;br /&gt;
&lt;br /&gt;
Arabic, Bengali, Greek, Hindi, Japanese, Kinyarwanda, Tamil, Vietnamese.&lt;br /&gt;
&lt;br /&gt;
With some localization done on a total of 86 languages.&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Activities that has been ported to sugar-toolkit-gtk3 will not run on older Sugar versions where the new toolkit is not available. Which means latest Browse and Read will not run on Sugar versions &amp;lt; 0.96. This is reflected in the activity providing backend ASLO where the activities are marked 0.96 only.&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package Sugar for your favorite distribution or just want to examine Sugar&#039;s lovely code here are the released bundles. If you are interested in the full changelog you can use the [http://git.sugarlabs.org/ Sugar git repositories].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.96.1.tar.bz2 sugar 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.96.0.tar.bz2 sugar-datastore 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.96.1.tar.bz2 sugar-toolkit 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit-gtk3/sugar-toolkit-gtk3-0.96.1.tar.bz2 sugar-toolkit-gtk3 0.96.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.96.0.tar.bz2 sugar-base 0.96.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.96.2.tar.bz2 sugar-artwork 0.96.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-5.0.2403.tar.gz etoys 5.0.2403]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-46.tar.bz2 Pippy 46]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-137.tar.bz2 Browse 137]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-40.tar.bz2 Calculate 40]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-76.tar.bz2 Chat 76]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-139.tar.bz2 TurtleArt 139]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-23.tar.bz2 Jukebox 23]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-28.tar.bz2 Log 28]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-20.tar.bz2 ImageViewer 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-79.tar.bz2 Write 79]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Terminal/Terminal-36.tar.bz2 Terminal 36]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Read/Read-99.tar.bz2 Read 99]&lt;br /&gt;
&lt;br /&gt;
== How to contribute with testing ==&lt;br /&gt;
Sugar 0.96 has been released. We are still stabilizing the areas that have seen major changes like the new stugar-toolkit-gtk3 the new GTK+ 3 Sugar theme and the Browse activity that has been ported to use Webkit. It is very important to get feedback from and that you report the bugs you find. The order of stability depends among other things as well on &#039;&#039;&#039;you&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
If you find bugs please report them into the [http://bugs.sugarlabs.org/ Sugar Labs bug tracker] indicating the 0.96.x version in the ticket version field. If you have hardware from OLPC you can use the [http://build.laptop.org/12.1.0/  12.1.0 builds] for the i686 architecture (XO 1 and XO 1.5) and the ARM architecture (XO 1.75). Those builds include the latest Sugar 0.96.x. Hardware specific bugs especially with the new 1.75 hardware please report at the [http://dev.laptop.org/ OLPC bug tracker]. The current development version is as well available in [http://fedoraproject.org/wiki/Releases/17 Fedora 17] and [[Development_Team/Jhbuild |sugar-jhbuild]] (sugar* master branches).&lt;br /&gt;
&lt;br /&gt;
==Credits==&lt;br /&gt;
This cycle we want to espacially thank the contributors to the GTK+ 3/pygobject3 port of the toolkit! All the attendees of the [[Marketing_Team/Events/Gtk3_Hackfest_2011]] in Praha and the Rosario meetup our warmest &amp;quot;thank you&amp;quot;. Kudos go to the Palette people!&lt;br /&gt;
&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes and do review other&#039;s patches,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing a Sugar version to test with during the development cycle,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;br /&gt;
&lt;br /&gt;
== Looking forward to 0.98==&lt;br /&gt;
In the 0.98 development cycle the porting of the Shell to GTK+ 3 and pygobject3 is a major task. Furthermore the remaining bugs in the new sugar-toolkit-gtk3 should be fixed. We encourage activity developers to port their activity to the new toolkit and GTK+ 3 and pygobject3.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=76550</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=76550"/>
		<updated>2012-03-18T16:20:18Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Presence */ add link to collaboration section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. See [[#Collaboration|below]] for details&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70590</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70590"/>
		<updated>2011-11-01T11:18:56Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Startup */ mention &amp;quot;unshared&amp;quot; startup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
If a room is found, the activity needs to join it immediately (see [[#Joining|below]]). Otherwise, a normal &amp;quot;unshared&amp;quot; activity startup should commence.&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70589</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70589"/>
		<updated>2011-11-01T11:16:22Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Telepathy */ connection availability&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one. Since connections can become available later, you need to either track changes using D-Bus signals, or do the above every time a new connection is needed.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. If so, it needs to be joined (see [[#Joining|below]]). The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70588</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70588"/>
		<updated>2011-11-01T11:13:27Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Collaboration */ clarify multiple connections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
This gathers all the usable connections, there may be more than one.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check all the currently available connections if there is already a &amp;quot;room&amp;quot; for it. If so, it needs to be joined (see [[#Joining|below]]). The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70587</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70587"/>
		<updated>2011-11-01T11:09:36Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Telepathy */ link to dev manual&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification] and the [http://telepathy.freedesktop.org/doc/book/ Telepathy Manual]. The code below is pseudo code, you need to adapt it for your specific programming language.&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
There may be more than one valid connection.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check if there is already a &amp;quot;room&amp;quot; for it. If so, it needs to be joined (see [[#Joining|below]]). The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Telepathy&amp;diff=70586</id>
		<title>Telepathy</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Telepathy&amp;diff=70586"/>
		<updated>2011-11-01T11:03:57Z</updated>

		<summary type="html">&lt;p&gt;Bert: Link to telepathy.freedesktop.org&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Extensive documentation can be found at [http://telepathy.freedesktop.org/ telepathy.freedesktop.org].&lt;br /&gt;
&lt;br /&gt;
There is some older (possibly outdated) documentation on the [[olpc:Telepathy|OLPC wiki]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Python modules]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70579</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70579"/>
		<updated>2011-10-31T23:48:42Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Collaboration */ AccountManager&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Telepathy ==&lt;br /&gt;
&lt;br /&gt;
For details, please refer to the [http://telepathy.freedesktop.org/spec/ Telepathy Specification].&lt;br /&gt;
&lt;br /&gt;
The entry point to Telepathy is the AccountManager:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Interface:   org.freedesktop.Telepathy.AccountManager&lt;br /&gt;
 Object Path: /org/freedesktop/Telepathy/AccountManager&lt;br /&gt;
&lt;br /&gt;
It has a list of valid Accounts. Each account has a Connection property, which is valid if its D-Bus path is not &#039;/&#039;, and connected if the account&#039;s ConnectionStatus property is 0 (1 means connecting, 2 disconnected). &lt;br /&gt;
&lt;br /&gt;
 accounts = accountManager.Get(&#039;ValidAccounts&#039;)&lt;br /&gt;
 for account in accounts:&lt;br /&gt;
     connection = account.Get(&#039;Connection&#039;)&lt;br /&gt;
     if connection.path != &#039;/&#039; &amp;amp;&amp;amp; account.Get(&#039;ConnectionStatus&#039;) == 0:&lt;br /&gt;
         connections.add(connection)&lt;br /&gt;
&lt;br /&gt;
There may be more than one valid connection.&lt;br /&gt;
&lt;br /&gt;
== Startup ==&lt;br /&gt;
&lt;br /&gt;
On startup, an activity needs to check if there is already a &amp;quot;room&amp;quot; for it. If so, it needs to be joined (see [[#Joining|below]]). The GetActivity method checks for the room given an activity_id:&lt;br /&gt;
&lt;br /&gt;
 for connection in connections:&lt;br /&gt;
     room_handle = connection.GetActivity(activityId)               # may fail&lt;br /&gt;
&lt;br /&gt;
It is provided by the non-standard ActivityProperties interface:&lt;br /&gt;
&lt;br /&gt;
 INTERFACE org.laptop.Telepathy.ActivityProperties&lt;br /&gt;
 METHOD GetActivity(activity_id:s) =&amp;gt; (room:u)&lt;br /&gt;
 METHOD GetProperties(room:u) =&amp;gt; (properties:a{sv})&lt;br /&gt;
 METHOD SetProperties(room:u, properties:a{sv}) =&amp;gt; ()&lt;br /&gt;
 SIGNAL ActivityPropertiesChanged(room:u, properties:a{sv})&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
If the activity finds itself to be shared already on startup, or the user chooses to enable sharing later, it needs to &amp;quot;join&amp;quot; the room used for communication:&lt;br /&gt;
&lt;br /&gt;
* create text channel&lt;br /&gt;
* create tubes channel&lt;br /&gt;
* add self to group&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Communicating ==&lt;br /&gt;
&lt;br /&gt;
This depends on the needs of the activity, but in general it would&lt;br /&gt;
&lt;br /&gt;
* create a tube in tubes channel&lt;br /&gt;
* use the tube for communication&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70578</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70578"/>
		<updated>2011-10-31T19:46:58Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Collaboration */ Start documenting Telepathy API&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Collaboration =&lt;br /&gt;
&lt;br /&gt;
Sharing and collaboration are core principles in Sugar. They are implemented using [[Telepathy]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;The [[#Presence|Presence Service]] (which was a wrapper around Telepathy in earlier Sugar releases) has been deprecated. Activities need to use Telepathy directly.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Sharing ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Inviting ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Joining ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Leaving ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be documented&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70577</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70577"/>
		<updated>2011-10-31T19:15:33Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Presence */ Presence Service has been deprecated. Use Telepathy instead.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: The Presence Service has been deprecated. Activities need to talk to [[Telepathy]] directly instead. Details on that will be added to this page soonish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;to be continued. In the mean time, see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70576</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70576"/>
		<updated>2011-10-31T19:11:01Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Activity Life Cycle */ another Presence Service mention&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like Telepathy (the collaboration framework).&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;to be continued. In the mean time, see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70575</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=70575"/>
		<updated>2011-10-31T19:07:46Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Activity Life Cycle */ remove Presence Service mention&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# It needs to set up collaboration by connecting to the shared activity instance (if any).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like the Presence Service.&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it needs to create a shared activity instance.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;to be continued. In the mean time, see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Marketing_Team/Events/Gtk3_Hackfest_2011&amp;diff=70532</id>
		<title>Marketing Team/Events/Gtk3 Hackfest 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Marketing_Team/Events/Gtk3_Hackfest_2011&amp;diff=70532"/>
		<updated>2011-10-30T10:20:22Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Impressions */ added beer photo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
= Gtk3 Hackfest 2011 =&lt;br /&gt;
Two major changes have recently occurred in Sugar&#039;s underlying technologies. Firstly, GTK+ 2 has been obsoleted by GTK+ 3, and GNOME is now based on GTK+ 3. Secondly, PyGTK, the underlying Python library that Sugar uses to call into GTK+, has been deprecated in favour of PyGObject Introspection (hereafter &amp;quot;PyGI&amp;quot;). More background info can be found at [[Features/GTK3]]. Goal of this hackfest is to remove the biggest blockers before we can start the porting and potentially start porting over.&lt;br /&gt;
&lt;br /&gt;
[[File:Brmlab_impressions.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
== Event Details ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Praha (Prague), Czech Republic&lt;br /&gt;
&lt;br /&gt;
The hackfest will be held at the [http://brmlab.cz/| brmlab a hackerspace in Prague]. The place is located [http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=Bubensk%C3%A1+1,+Praha-Praha+7,+%C4%8Cesk%C3%A1+republika&amp;amp;sll=37.0625,-95.677068&amp;amp;sspn=65.390746,135.263672&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=Bubensk%C3%A1+1477/1,+170+00+Praha+7-Hole%C5%A1ovice,+Czech+Republic&amp;amp;view=map|Map here], using [http://idos.dpp.cz/idos/ConnForm.aspx?tt=pid&amp;amp;cl=E5|Prague public transport] you can get here easily, just hop off at (Metro &amp;amp; Tram stop: &amp;quot;Vltavska&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Date:&#039;&#039;&#039; Friday, October 28th - Sunday October 30th 2011&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Primary contact:&#039;&#039;&#039; Simon Schampijer &amp;lt;simon AT laptop DOT org&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Secondary contact:&#039;&#039;&#039; Tomeu Vizoso &amp;lt;tomeu.vizoso AT collabora DOT co DOT uk&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Target audience ==&lt;br /&gt;
Sugar developers&lt;br /&gt;
&lt;br /&gt;
== Sponsors ==&lt;br /&gt;
[[File:Brmlab.jpg|300px]] We want to thank [http://brmlab.cz/| brmlab] for hosting us during the week.&lt;br /&gt;
&lt;br /&gt;
[[File:Olpc_logo.png|300px]] We want to thank the [http://laptop.org OLPC Foundation] for sponsoring regional trips to the event.&lt;br /&gt;
&lt;br /&gt;
== Sponsoring regional trips ==&lt;br /&gt;
This Hackfest is sponsored by the [http://laptop.org OLPC Foundation]. If you need help for funding your travel, please send an email to simon AT laptop DOT org before 8th of October 2011. We won&#039;t be able to refund more than 150 USD per trip, and we will fund regional (european) travels in priority.&lt;br /&gt;
&lt;br /&gt;
== Agenda, goals ==&lt;br /&gt;
* Removing Hippo and other custom widgets&lt;br /&gt;
** Do we do this before or after GTK3? Note transparent window / icon overlapping issue.&lt;br /&gt;
* migration path to Gtk3 (do we ship two toolkits? Do we migrate the shell and the toolkit and activities at once?)&lt;br /&gt;
** This is expected to be resolved in advance at [[Features/GTK3]].&lt;br /&gt;
* porting Sugar&#039;s theme to gtk3 (go benzea, go!)&lt;br /&gt;
* Port sugar-toolkit to GTK3 and release sugar-toolkit-0.95.x&lt;br /&gt;
* Port Read to GTK3&lt;br /&gt;
* Port Browse to Webkit/GTK3&lt;br /&gt;
* other introspected libraries that need work (namely NM)&lt;br /&gt;
&lt;br /&gt;
== Measuring your success ==&lt;br /&gt;
&#039;&#039;coming soon...&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Attendants ==&lt;br /&gt;
&lt;br /&gt;
Are you planning to attend?  Add your name and contact info below!&lt;br /&gt;
# [[User:Erikos | Simon Schampijer]]&lt;br /&gt;
# [[User:Tomeu | Tomeu Vizoso]]&lt;br /&gt;
# [[User:Rgs | Raúl Gutiérrez Segalés]]&lt;br /&gt;
# [[User:Walter | Walter Bender]]&lt;br /&gt;
# [[User:BenjaminBerg | Benjamin Berg]]&lt;br /&gt;
# [[User:DanielDrake | Daniel Drake]]&lt;br /&gt;
# [[User:marcopg|Marco Pesenti Gritti]]&lt;br /&gt;
# [[User:Cjb|Chris Ball]] (just for Friday, in Prague 22-28 Oct for Kernel Summit/LinuxCon)&lt;br /&gt;
# [[User:Ritafreudenberg|Rita Freudenberg]] &lt;br /&gt;
# [[User:bert|Bert Freudenberg]]&lt;br /&gt;
# [[Martin Schüssler]]&lt;br /&gt;
&lt;br /&gt;
== Accommodation ==&lt;br /&gt;
This is a table to find out when people do need accommodation during the hackfest.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Name !! 27.10.11 !! 28.10.11 !! 29.10.11 !! 30.10.11 !! 31.10.11 !! Note&lt;br /&gt;
|-&lt;br /&gt;
! Simon Schampijer&lt;br /&gt;
| - || yes || yes || yes || - || -&lt;br /&gt;
|-&lt;br /&gt;
! Raúl Gutiérrez Segalés&lt;br /&gt;
| yes || yes || yes || yes || yes || -&lt;br /&gt;
|-&lt;br /&gt;
! Walter Bender&lt;br /&gt;
| yes || yes || yes || yes || yes || -&lt;br /&gt;
|-&lt;br /&gt;
! Benjamin Berg&lt;br /&gt;
| - || yes || yes || yes || - || Arriving 28.10. 10:15; leaving 31.10. 18:31 Uhr&lt;br /&gt;
|-&lt;br /&gt;
! Daniel Drake&lt;br /&gt;
| - || yes || yes || yes || - || travel confirmed: arriving 28th at 10:20, leaving 31st at 06:00&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Lodging ==&lt;br /&gt;
This one does seem to be a reasonable offer: http://www.booking.com/hotel/cz/plus-prague-hostel.en-us.html?sid=efb1e369a800d8137da1013763ae00e9;checkin=2011-10-27;checkout=2011-10-30;srfid=8d0e0147ab19098770fd94887bfca1e1X1&lt;br /&gt;
&lt;br /&gt;
== Schedule ==&lt;br /&gt;
&lt;br /&gt;
=== Friday, October 28 ===&lt;br /&gt;
&lt;br /&gt;
=== Saturday, October 29 ===&lt;br /&gt;
&lt;br /&gt;
=== Sunday, October 30 ===&lt;br /&gt;
&lt;br /&gt;
== Impressions ==&lt;br /&gt;
&#039;&#039;link your photos, add your comments here&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Hackfest-Prague-2011.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Event]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Hackfest-Prague-2011.jpg&amp;diff=70531</id>
		<title>File:Hackfest-Prague-2011.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Hackfest-Prague-2011.jpg&amp;diff=70531"/>
		<updated>2011-10-30T10:18:07Z</updated>

		<summary type="html">&lt;p&gt;Bert: Saturday night beer at Tomeu&amp;#039;s favorite pub. Great beer. Photo by Bert Freudenberg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Saturday night beer at Tomeu&#039;s favorite pub. Great beer. Photo by [[User:bert|Bert Freudenberg]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66636</id>
		<title>Talk:Licensing</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66636"/>
		<updated>2011-06-24T15:11:14Z</updated>

		<summary type="html">&lt;p&gt;Bert: nag&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;DRAFT of new Licensing text as per the discussion at the 9 June 2011 SLOBs meeting&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sugar Labs adheres to the principles of Free Software. An [http://www.gnu.org/philosophy/free-sw.html overview of these principles] is found on the [http://gnu.org FSF.org website]. The OSD has a [http://opensource.org/docs/osd set of guidelines for Free and Open Source software] that characterize the intentions of our community.&lt;br /&gt;
&lt;br /&gt;
All software and content distributed by Sugar Labs, including activity bundles uploaded to http://activities.sugarlabs.org, must be released under a license that conforms to the principles and guidelines referred to above.&lt;br /&gt;
&lt;br /&gt;
You may use any license on the Fedora Project&#039;s [http://fedoraproject.org/wiki/Licensing#Good_Licenses list of Good Licenses] or the FSF&#039;s [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses]. If you wish to use a license not on one of these two lists and believe that it fits our guidelines, please contact the [[Oversight Board]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
This policy was determined during a [[Oversight_Board/2009/Meeting_Minutes-2009-12-11#Non-FOSS_content|2009-12-11 board meeting]] and clarified at the [http://meeting.sugarlabs.org/sugar-meeting/2011-06-09#i_2671836 2011-06-09 board meeting].&lt;br /&gt;
&lt;br /&gt;
Please contact the [[Oversight Board]] if you have questions about our licensing policy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
+1 to the above text from me! [[User:Bernie|bernie]] 03:29, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
+1 from Cjb, with the fix to one of the links that I just made. [[User:Cjb|Cjb]] 09:45, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;The language seems sloppy to me. Fedora lists both good and bad licenses on the linked page, so saying &amp;quot;You may use any license&amp;quot;  from there is not quite what is meant. Secondly, the FSF link goes only to the GNU licenses, perhaps their [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses] is more appropriate?&#039;&#039; [[User:Bert|Bert]] 09:15, 24 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
:Sorry. I realize I had the wrong link. Should be http://www.gnu.org/licenses/license-list.html which includes many non-GNU licenses. --[[User:Walter|Walter]] 09:21, 24 June 2011 (EDT)&lt;br /&gt;
:The problem with the Fedora link was a typo. Should link directly to http://fedoraproject.org/wiki/Licensing#Good_Licenses now. --[[User:Walter|Walter]] 09:23, 24 June 2011 (EDT)&lt;br /&gt;
:: Maybe just to be explicit, write &amp;quot;Good Licenses&amp;quot; instead of &amp;quot;acceptable licenses&amp;quot;? [[User:Bert|Bert]] 09:54, 24 June 2011 (EDT)&lt;br /&gt;
::: Yes. I agree... consistency. --[[User:Walter|Walter]] 10:02, 24 June 2011 (EDT)&lt;br /&gt;
&#039;&#039;Another nit pick: I find the second link to the GNU.org website distracting and unnecessary. I&#039;d replace &#039;&#039;&amp;quot;is found on the [http://gnu.org GNU.org website]&amp;quot;&#039;&#039; with &#039;&#039;&amp;quot;is provided by the FSF&amp;quot;&#039;&#039;.  The FSF is mentioned again later, so it&#039;s better to use the same name. [[User:Bert|Bert]] 10:04, 24 June 2011 (EDT)&lt;br /&gt;
:Nitpicking is right... but I made the change :) --[[User:Walter|Walter]] 10:51, 24 June 2011 (EDT)&lt;br /&gt;
:: That&#039;s better, though I&#039;d remove that link altogether. It adds nothing to the official Sugar Labs Licensing page. My suggestion was &amp;quot;is provided by the FSF&amp;quot;, with no embedded link at all. [[User:Bert|Bert]] 11:11, 24 June 2011 (EDT)&lt;br /&gt;
---- &lt;br /&gt;
&lt;br /&gt;
+1, having Fedora list of good licences will simplify workflow on ASLO to make it automatic, ie, activities-testing.sugarlabs.org [[Activity_Library/Editors/Policy/Licensing|sees]] to the {{Code|licence}} tag in the {{Code|activitiy.info}} to accept/reject any new upload. [[User:Alsroot|alsroot]] 09:32, 24 June 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66634</id>
		<title>Talk:Licensing</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66634"/>
		<updated>2011-06-24T14:04:23Z</updated>

		<summary type="html">&lt;p&gt;Bert: suggest rephrasing FSF link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;DRAFT of new Licensing text as per the discussion at the 9 June 2011 SLOBs meeting&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sugar Labs adheres to the principles of Free Software. An [http://www.gnu.org/philosophy/free-sw.html overview of these principles] is found on the [http://gnu.org GNU.org website]. The OSD has a [http://opensource.org/docs/osd set of guidelines for Free and Open Source software] that characterize the intentions of our community.&lt;br /&gt;
&lt;br /&gt;
All software and content distributed by Sugar Labs, including activity bundles uploaded to http://activities.sugarlabs.org, must be released under a license that conforms to the principles and guidelines referred to above.&lt;br /&gt;
&lt;br /&gt;
You may use any license on the Fedora Project&#039;s [http://fedoraproject.org/wiki/Licensing#Good_Licenses list of Good Licenses] or the FSF&#039;s [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses]. If you wish to use a license not on one of these two lists and believe that it fits our guidelines, please contact the [[Oversight Board]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
This policy was determined during a [[Oversight_Board/2009/Meeting_Minutes-2009-12-11#Non-FOSS_content|2009-12-11 board meeting]] and clarified at the [http://meeting.sugarlabs.org/sugar-meeting/2011-06-09#i_2671836 2011-06-09 board meeting].&lt;br /&gt;
&lt;br /&gt;
Please contact the [[Oversight Board]] if you have questions about our licensing policy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
+1 to the above text from me! [[User:Bernie|bernie]] 03:29, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
+1 from Cjb, with the fix to one of the links that I just made. [[User:Cjb|Cjb]] 09:45, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;The language seems sloppy to me. Fedora lists both good and bad licenses on the linked page, so saying &amp;quot;You may use any license&amp;quot;  from there is not quite what is meant. Secondly, the FSF link goes only to the GNU licenses, perhaps their [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses] is more appropriate?&#039;&#039; [[User:Bert|Bert]] 09:15, 24 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
:Sorry. I realize I had the wrong link. Should be http://www.gnu.org/licenses/license-list.html which includes many non-GNU licenses. --[[User:Walter|Walter]] 09:21, 24 June 2011 (EDT)&lt;br /&gt;
:The problem with the Fedora link was a typo. Should link directly to http://fedoraproject.org/wiki/Licensing#Good_Licenses now. --[[User:Walter|Walter]] 09:23, 24 June 2011 (EDT)&lt;br /&gt;
:: Maybe just to be explicit, write &amp;quot;Good Licenses&amp;quot; instead of &amp;quot;acceptable licenses&amp;quot;? [[User:Bert|Bert]] 09:54, 24 June 2011 (EDT)&lt;br /&gt;
::: Yes. I agree... consistency. --[[User:Walter|Walter]] 10:02, 24 June 2011 (EDT)&lt;br /&gt;
&#039;&#039;Another nit pick: I find the second link to the GNU.org website distracting and unnecessary. I&#039;d replace &#039;&#039;&amp;quot;is found on the [http://gnu.org GNU.org website]&amp;quot;&#039;&#039; with &#039;&#039;&amp;quot;is provided by the FSF&amp;quot;&#039;&#039;.  The FSF is mentioned again later, so it&#039;s better to use the same name. [[User:Bert|Bert]] 10:04, 24 June 2011 (EDT)&lt;br /&gt;
---- &lt;br /&gt;
&lt;br /&gt;
+1, having Fedora list of good licences will simplify workflow on ASLO to make it automatic, ie, activities-testing.sugarlabs.org [[Activity_Library/Editors/Policy/Licensing|sees]] to the {{Code|licence}} tag in the {{Code|activitiy.info}} to accept/reject any new upload. [[User:Alsroot|alsroot]] 09:32, 24 June 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66632</id>
		<title>Talk:Licensing</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66632"/>
		<updated>2011-06-24T13:54:24Z</updated>

		<summary type="html">&lt;p&gt;Bert: suggest link title &amp;quot;Good Licenses&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;DRAFT of new Licensing text as per the discussion at the 9 June 2011 SLOBs meeting&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sugar Labs adheres to the principles of Free Software. An [http://www.gnu.org/philosophy/free-sw.html overview of these principles] is found on the [http://gnu.org GNU.org website]. The OSD has a [http://opensource.org/docs/osd set of guidelines for Free and Open Source software] that characterize the intentions of our community.&lt;br /&gt;
&lt;br /&gt;
All software and content distributed by Sugar Labs, including activity bundles uploaded to http://activities.sugarlabs.org, must be released under a license that conforms to the principles and guidelines referred to above.&lt;br /&gt;
&lt;br /&gt;
You may use any license on the Fedora Project&#039;s [http://fedoraproject.org/wiki/Licensing#Good_Licenses list of acceptable licenses] or the FSF&#039;s [http://www.gnu.org/licenses/license-list.html list of Free Software licenses]. If you wish to use a license not on one of these two lists and believe that it fits our guidelines, please contact the [[Oversight Board]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
This policy was determined during a [[Oversight_Board/2009/Meeting_Minutes-2009-12-11#Non-FOSS_content|2009-12-11 board meeting]] and clarified at the [http://meeting.sugarlabs.org/sugar-meeting/2011-06-09#i_2671836 2011-06-09 board meeting].&lt;br /&gt;
&lt;br /&gt;
Please contact the [[Oversight Board]] if you have questions about our licensing policy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
+1 to the above text from me! [[User:Bernie|bernie]] 03:29, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
+1 from Cjb, with the fix to one of the links that I just made. [[User:Cjb|Cjb]] 09:45, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;The language seems sloppy to me. Fedora lists both good and bad licenses on the linked page, so saying &amp;quot;You may use any license&amp;quot;  from there is not quite what is meant. Secondly, the FSF link goes only to the GNU licenses, perhaps their [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses] is more appropriate?&#039;&#039; [[User:Bert|Bert]] 09:15, 24 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
:Sorry. I realize I had the wrong link. Should be http://www.gnu.org/licenses/license-list.html which includes many non-GNU licenses. --[[User:Walter|Walter]] 09:21, 24 June 2011 (EDT)&lt;br /&gt;
:The problem with the Fedora link was a typo. Should link directly to http://fedoraproject.org/wiki/Licensing#Good_Licenses now. --[[User:Walter|Walter]] 09:23, 24 June 2011 (EDT)&lt;br /&gt;
:: Maybe just to be explicit, write &amp;quot;Good Licenses&amp;quot; instead of &amp;quot;acceptable licenses&amp;quot;? [[User:Bert|Bert]] 09:54, 24 June 2011 (EDT)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
+1, having Fedora list of good licences will simplify workflow on ASLO to make it automatic, ie, activities-testing.sugarlabs.org [[Activity_Library/Editors/Policy/Licensing|sees]] to the {{Code|licence}} tag in the {{Code|activitiy.info}} to accept/reject any new upload. [[User:Alsroot|alsroot]] 09:32, 24 June 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66627</id>
		<title>Talk:Licensing</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Talk:Licensing&amp;diff=66627"/>
		<updated>2011-06-24T13:15:24Z</updated>

		<summary type="html">&lt;p&gt;Bert: Remark on sloppy language, suggest better FSF link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;DRAFT of new Licensing text as per the discussion at the 9 June 2011 SLOBs meeting&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sugar Labs adheres to the principles of Free Software. An [http://www.gnu.org/philosophy/free-sw.html overview of these principles] is found on the [http://gnu.org GNU.org website]. The OSD has a [http://opensource.org/docs/osd set of guidelines for Free and Open Source software] that characterize the intentions of our community.&lt;br /&gt;
&lt;br /&gt;
All software and content distributed by Sugar Labs, including activity bundles uploaded to http://activities.sugarlabs.org, must be released under a license that conforms to the principles and guidelines referred to above.&lt;br /&gt;
&lt;br /&gt;
You may use any license on the Fedora Project&#039;s [http://fedoraproject.org/wiki/Licensing#Good_Licenses&#039;s list of acceptable licenses] or the FSF&#039;s [http://www.gnu.org/licenses/licenses.html list of licenses]. If you wish to use a license not on one of these two lists and believe that it fits our guidelines, please contact the [[Oversight Board]].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
This policy was determined during a [[Oversight_Board/2009/Meeting_Minutes-2009-12-11#Non-FOSS_content|2009-12-11 board meeting]] and clarified at the [http://meeting.sugarlabs.org/sugar-meeting/2011-06-09#i_2671836 2011-06-09 board meeting].&lt;br /&gt;
&lt;br /&gt;
Please contact the [[Oversight Board]] if you have questions about our licensing policy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
+1 to the above text from me! [[User:Bernie|bernie]] 03:29, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
+1 from Cjb, with the fix to one of the links that I just made. [[User:Cjb|Cjb]] 09:45, 15 June 2011 (EDT)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&#039;&#039;The language seems sloppy to me. Fedora lists both good and bad licenses on the linked page, so saying &amp;quot;You may use any license&amp;quot;  from there is not quite what is meant. Secondly, the FSF link goes only to the GNU licenses, perhaps their [http://www.gnu.org/licenses/license-list.html list of Free Software Licenses] is more appropriate?&#039;&#039; [[User:Bert|Bert]] 09:15, 24 June 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Emulator_image_files&amp;diff=66338</id>
		<title>Emulator image files</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Emulator_image_files&amp;diff=66338"/>
		<updated>2011-06-10T23:11:56Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Sugar on a Stick v3 Mirabelle */ works only with VirtualBox 3.2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Virtual machine or platform emulator]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other virtual machines==&lt;br /&gt;
&lt;br /&gt;
This is a quick guide to the locations of various forms of Sugar software that can run in QEMU emulation or VMware or VirtualBox virtualization.&lt;br /&gt;
&lt;br /&gt;
You can download installation images (.iso files) for Linux distributions that support Sugar and create your own bootable images with Sugar installed.&lt;br /&gt;
&lt;br /&gt;
See [[VirtualBox]], [[VMware]], or [[QEMU]] for more information on how to run an image, and [[Supported systems]] for more information on what is available.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
       This page is meant to be a brief index to recommended, downloadable images--not a discussion page for their use or features.  For experimental images, please refer readers to the appropriate software page elsewhere.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:wikipedia: &#039;&#039;&#039;[[wikipedia:Comparison_of_platform_virtual_machines|Comparison of platform virtual machines]]&#039;&#039;&#039; - Very nice comparison of features of Virtual Machines platforms&lt;br /&gt;
===[[File:VirtualBox.png|75px|link=VirtualBox]]&#039;&#039;&#039;[[VirtualBox]]&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
Latest version: &#039;&#039;&#039;VirtualBox 4.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Download: http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html&lt;br /&gt;
:&#039;&#039;Preliminary testing shows that VirtualBox Appliances from ver 3.1.10-12 import and function well in ver 4.0.x and visa-versa.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
* VirtualBox-4.0 is OSE version until you add: [http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html Oracle VM VirtualBox Extension Pack]&lt;br /&gt;
* Support for Windows, Mac OS X, Solaris, and GNU/Linux&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VMware Workstation xxx.vmdk Hard Disks will work as &amp;quot;existing Disks&amp;quot; in VirtualBox&#039;&#039;&#039;&lt;br /&gt;
* [http://www.virtualbox.org/manual/ VirtualBox Manual]&lt;br /&gt;
* [http://www.virtualbox.org/manual/ch08.html VBoxManage command line tool for VirtualBox] for advanced users&lt;br /&gt;
{{Admon/note|&lt;br /&gt;
* &#039;&#039;&#039;When making a new VM&#039;&#039;&#039;, to clear the Sugar Journal of old entries and to avoid identity conflicts among copies of the VM, enter the command {{Code|rm&amp;amp;nbsp;-rf&amp;amp;nbsp;~/.sugar}} in the Terminal activity. Then shutdown the VM. This will clear all Learner information on the VM and let you start with a fresh install. Skipping this will result in collisions in the Neighborhood view of the Jabber network between separate copies of the appliance. Verify the presence of the &#039;&#039;&#039;.sugar&#039;&#039;&#039; directory by entering {{Code|ls&amp;amp;nbsp;-a}} in Terminal.&lt;br /&gt;
* &#039;&#039;&#039;When cloning a customized VM&#039;&#039;&#039;, in order to keep the Journal and installed .xo Activities, use {{Code|rm&amp;amp;nbsp;~/.sugar/default/owner.key*}} in the Sugar Terminal, and then shutdown the VM. This leaves the Journal entries and removes only the previous Learner&#039;s identity key files.}}&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v3 Mirabelle&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;Sugar 0.88.0&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
::firstboot has not yet run; so a new user name and password will be set for the gdm login on startup for the first time&lt;br /&gt;
:How Built:&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
: 8-GB Virtual Box hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.vmdk 533M&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.ovf   12K&lt;br /&gt;
&lt;br /&gt;
*Note1:Use a later version of Oracle VM VirtualBox (3.2_10.8-64453 or later). Some appliances have multiple hard disc controllers and the earlier Sun VirtualBox 3.1 version does not support them. &#039;&#039;On a Mac this did not work with VirtualBox 4.0 for me. VirtualBox 3.2.12 was fine [http://www.virtualbox.org/wiki/Download_Old_Builds_3_2])&#039;&#039;&lt;br /&gt;
*Note2: All appliances were built on a MacBook Air with Oracle VM VirtualBox (3.2.10-r66523) then tested on a Ubuntu installation on an Acer Aspire One Netbook imported into VirtualBox (3.2.10 r66523)&lt;br /&gt;
*Note3:Set ControlPanel/Frame &amp;quot;Edge&amp;quot; slider to far left for easier access to sugar-frame features&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VMware Player Version&#039;&#039;&#039;&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Soas-v3-Mirabelle.zip Soas-v3-Mirabelle.zip Download]&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v4 Mango Lassi&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;Sugar 0.90.1&#039;&#039;&#039; &#039;&#039;Note Sugar 0.90.x is buggy, use a version of SoaS with the 0.88.1 version.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:user=sugar&lt;br /&gt;
:password=sugaruser&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
:How Built:&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-14-i686-Live-SoaS-2.ovf 12K&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-14-i686-Live-SoaS-2-disk1.vmdk  606M&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;had to modify the .ovf to get the image running on a X60 with ubuntu maverick:&#039;&#039;&#039;&lt;br /&gt;
 http://people.sugarlabs.org/dogi/virtualbox/Fedora-14-i686-Live-SoaS-2.1.ovf 12K&lt;br /&gt;
&lt;br /&gt;
*Note, this appliance has 1024x768 screensize available as VirtualBox extensions were compiled into the kernel.&lt;br /&gt;
&lt;br /&gt;
=====To Update Sugar=====&lt;br /&gt;
:Sugar update does not work in control panel&lt;br /&gt;
* In root sugar-terminal:&lt;br /&gt;
 yum groupinstall sugar-desktop&lt;br /&gt;
: (install 9 packages, Upgrade 10 packages) 02/02/2011 satellit&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v5 Coconut&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;sugar 0.92.1&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;this is the RC3 version; for testing only at this time&#039;&#039;&#039;&lt;br /&gt;
; Nightly compose .iso no longer available&lt;br /&gt;
:user=sugar&lt;br /&gt;
:password=sugaruser&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
:How Built:&lt;br /&gt;
:liveinst in root terminal to VirtualBox HD&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;Cleared of Identity- starts at click to change color after gdm login&#039;&#039;&#039;&lt;br /&gt;
::Etoys fixed so it starts&lt;br /&gt;
::sub-menus work on activities&lt;br /&gt;
::Jabber fills up with duplicate avitars that constantly change colors en-mass.&lt;br /&gt;
::http://bugs.sugarlabs.org/ticket/2845&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Soas-v5_RC3_Live_CE.ovf  12.5KB&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Soas-v5_RC3_Live_CE-disk1.vmdk  621 MB&lt;br /&gt;
*Login at gdm: sugaruser&lt;br /&gt;
; TO UPDATE&lt;br /&gt;
 sugar-terminal&lt;br /&gt;
 su&lt;br /&gt;
 password: sugarroot&lt;br /&gt;
 yum update&lt;br /&gt;
*Problems: f1 Neighborhood does not see Jabber&lt;br /&gt;
&lt;br /&gt;
====f15-Gnome3-Ver3.0.0-Virtual Box-Appliance====&lt;br /&gt;
*download these 2 files and import them:&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/F15-gnome3_Desktop_sugar_cl-disk1.vmdk&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/F15-gnome3_Desktop_sugar_cl.ovf&lt;br /&gt;
; Starts in gnome3 fallback mode as VirtualBox does not support hardware acceleration&lt;br /&gt;
::user=sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
:Cleared of sugar identity&#039; starts on select color by clicking on XO icon&lt;br /&gt;
:use &amp;lt;== arrow to write your custom name then ==&amp;gt; to finish&lt;br /&gt;
*Sugar-emulator is in Activities/Education/Sugar&lt;br /&gt;
:::enter user password for keychain (sugaruser) on time and cancel until pop-up finishes (this is a bug in keychain in f15)&lt;br /&gt;
:Surf-115 is the browser as Browse-120 does not start (known bug)&lt;br /&gt;
&lt;br /&gt;
====f14-SoaS====&lt;br /&gt;
*download these 2 files and import them:&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/Fedora_14_SoaS.ovf&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/Fedora_14_SoaS-disk1.vmdk&lt;br /&gt;
::user=sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
*firstboot has not yet been run.&lt;br /&gt;
:Sugar on a Stick 4 (Mango Lassi)&lt;br /&gt;
:sugar: 0.90.1&lt;br /&gt;
*Bugs:&lt;br /&gt;
:: Control Panel/Software Update does not work.&lt;br /&gt;
:: Delay in start (edit to uncheck floppy disk)&lt;br /&gt;
&lt;br /&gt;
====[[File:trisquel_logo.png]][http://people.sugarlabs.org/Tgillard/Trisquel41_sugar_installer.iso Trisquel41_sugar INSTALLER ISO][[File:CD.png]]====&lt;br /&gt;
&lt;br /&gt;
:Revised 03/02/2011 to remove sugar identity&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
*click above link^ to download 1.2GB  DVD which contains&lt;br /&gt;
 32bit-VirtualBox Installers (OSE) (Directory with install files for VirtualBox 4.0.4)&lt;br /&gt;
 &#039;&#039;&#039;(Does not include Free for Personal Use licensed extension pack)&#039;&#039;&#039; - includes instructions on how to download them for personal use.&lt;br /&gt;
 ReadMeFirst_Install_Instructions.pdf  (Instructions-how to install VirtualBox and import appliance)&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18.ovf&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18-disk1.vmdk&lt;br /&gt;
 UserManual.pdf (VirtualBox 4.0.4 User Manual-269 pages)&lt;br /&gt;
: Instructions and .vmdk/.ovf files to import&lt;br /&gt;
* Cleared of sugar identity Starts on Color Selection Screen ( &amp;lt;===(back) to change name)&lt;br /&gt;
{{Admon/faq|Question|Does this contain Oracle VirtualBox binaries that are not redistributable under their [http://www.virtualbox.org/wiki/Licensing_FAQ licensing]?&amp;lt;br&amp;gt;We may need their permission to redistribute some of their software.  &#039;&#039;&#039;see listing above of contents for answer&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]] Trisquel-Gnome-sugar 4.5 Release Candidate====&lt;br /&gt;
::[http://devel2.trisquel.info/slaine/iso/ trisquel 4.5 Download]&lt;br /&gt;
: XChat; sweets-sugar 0.88.1; surf115-xo; updated; cleared of identity; autostart &lt;br /&gt;
::User=sugar&lt;br /&gt;
::password sugaruser&lt;br /&gt;
*&amp;quot;Free Distibution&amp;quot;&lt;br /&gt;
*Ubuntu 10.10 based&lt;br /&gt;
* Trisquel 4.5 RC VirtualBox 4.0.4 appliance &lt;br /&gt;
:Download and Import these files:&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/trisquel_4.5-RC_i686surf115-cleared.ovf&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/trisquel_4.5-RC_i686surf115-cleared-disk1.vmdk&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.5 -Gnome-sugar BETA|Trisquel-4.5 -Gnome-sugar BETA]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Gnome and Sugar 0.88.1&lt;br /&gt;
*: Beta, so not for Production use, but quite stable for testing&lt;br /&gt;
* [http://devel2.trisquel.info/slaine/iso/ Trisquel 4.5 Download]&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* Sugar sweets 0.88.1 with 30 applications:  [[Trisquel_On_A_Sugar_Toast#Install_Sugar-desktop_0.88_.22SWEETS.22|How to install sweets-sugar-desktop 0.88.1]]&lt;br /&gt;
*: Updated 02/04/2011 (System/Administration/Update Manager)&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/Tris-45-Sugar0801-4.ovf           13K&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/Tris-45-Sugar0801-4-disk1.vmdk   1.4G  &lt;br /&gt;
&lt;br /&gt;
*NOTE: This is a Beta version.  A lot of updates are still coming in.&lt;br /&gt;
*: Sugar 0.88.1 is a much more stable release than sugar 0.90.1&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.1-sugar|Trisquel-4.1-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
* Sugar sweets 0.88.1&lt;br /&gt;
*:NEW: 02/18/2011 2nd Beta Version with application fixes&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned-disk1.vmdk&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned.ovf&lt;br /&gt;
&lt;br /&gt;
* Cleared of sugar identity Starts on Color Selection Screen ( &amp;lt;===(back) to change name) 03/02/2011&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.0.1-Gnome-sugar|Trisquel-4.0.1-Gnome-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Gnome and Sugar 0.90.1&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* Updated 12/23/2010&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/trisquel_4.0.1_ext4-sugar0901.ovf 13K&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/trisquel_4.0.1_ext4.vmdk 2.1 GB&lt;br /&gt;
&lt;br /&gt;
* VMware Player Version&lt;br /&gt;
*:[http://download.sugarlabs.org/images/vmplayer/Trisquel-4-sugar-VMPlayer.zip Trisquel-4-sugar-VMPlayer Download]&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-3-sugar|Trisquel-3-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Sugar 0.86.2&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/Trisquel-3-sugar-sugaruser.vmdk 543M&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/Trisquel-3-sugar-sugaruser.ovf   12K&lt;br /&gt;
&lt;br /&gt;
* VMware Player Version&lt;br /&gt;
*:[http://download.sugarlabs.org/images/vmplayer/Trisquel3.zip Trisquel3.zip Download]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;20 new applications were installed by CP/software update&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====[[Image:Debian-small.jpg]]&#039;&#039;&#039;Debian-squeeze-Gnome-sugar&#039;&#039;&#039;====&lt;br /&gt;
::&#039;&#039;&#039;Full Gnome Desktop plus Sugar 0.88.1&#039;&#039;&#039;&lt;br /&gt;
::[http://wiki.sugarlabs.org/go/Community/Distributions/Debian Debian Information]&lt;br /&gt;
:Updated 12/05/2010 includes activities Downloaded from ASLO as .xo files; and sugar-emulator.&lt;br /&gt;
::Log in as sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Debian-sugaruser.vmdk  2.1G&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Debian-sugaruser-1.ovf 14K&lt;br /&gt;
&lt;br /&gt;
====[[Image:Mandriva-small.png]]&#039;&#039;&#039;Mandriva-linux-one-2010.1-Gnome-sugar&#039;&#039;&#039;====&lt;br /&gt;
::&#039;&#039;&#039;Full Gnome Desktop plus Sugar-0.88.0&#039;&#039;&#039;&lt;br /&gt;
::[http://wiki.sugarlabs.org/go/Community/Distributions/Mandriva Mandriva Information]&lt;br /&gt;
:::Note Log into gnome desktop first to enable networking then start sugar-emulator &lt;br /&gt;
::Log in as sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugaruser&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
  download and import 2 files:&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/mandriva-linux-one-2010-sugaruser-plus.ovf  14K &lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/mandriva-linux-one-2010.vmdk  1.4G&lt;br /&gt;
&lt;br /&gt;
Info:&lt;br /&gt;
: [http://www2.mandriva.com/downloads/free/ 2010.2 free DVD Download]&lt;br /&gt;
: [http://wiki.mandriva.com/en/Mandriva_Linux_2010.1 Mandriva_Linux_2010.1 Download]&lt;br /&gt;
: [http://www2.mandriva.com/en/linux/overview/ Mandriva 2010.1 Features]&lt;br /&gt;
: [http://www2.mandriva.com/en/news/?p=145&amp;amp;s=0 The Brazilian government education authority has selected Intel-powered classmate PCs running Mandriva Linux for educational use nationwide.]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[:File:MacBook_Air-Virtualbox.jpg|Photo of Neighborhood view on MacBook Air-Mandriva 2010.1]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Note: The above appliances were built on a MacBook Air with Oracle VM VirtualBox (3.2.10-r66523) then tested on a Ubuntu installation on an Acer Aspire One Netbook imported into VirtualBox (3.2.10 r66523)&lt;br /&gt;
&lt;br /&gt;
====Some Suggestions on Using VirtualBox====&lt;br /&gt;
* Export your appliances to an external USB hard disk&lt;br /&gt;
*: This functions like the Mac Application &amp;quot;Time Machine&amp;quot;&lt;br /&gt;
*: Save each exported Appliance in a folder marked with the name and date of export.&lt;br /&gt;
*::You can then import this Appliance to restore the state of the Appliance on that date.&lt;br /&gt;
&lt;br /&gt;
*Run an Existing VirtualBox Appliance from an external USB Hard Drive&lt;br /&gt;
*::Portable, Individual Copy for Student, Move between separate Computers.&lt;br /&gt;
*# copy-paste the xxxx.vmdk file from /(User)/Virtualbox/HardDisks/xxxx.vmdk to a Folder on an external USB HD&lt;br /&gt;
*# Menu: Machine&amp;gt;New&amp;gt;continue&amp;gt;Name&amp;gt;Operating System&amp;gt;Version/Memory/Continue&amp;gt;Use existing hard disk&amp;gt;[chose xxxx.vmdk on an External USB HD]&amp;gt; Start.&lt;br /&gt;
&lt;br /&gt;
* Note Running from a USB Memory Stick Crawls, VERY slowly - &#039;&#039;&#039;not practical&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Testing of appliance running from an external USB Hard Disk&lt;br /&gt;
:: Appears to depend on the Speed of the Host Machine: (needs farther testing)&lt;br /&gt;
# Very Slow -  Fedora-13-Soas/VB 3.2.12 on Windows XP SP2/ EeePC 1000HE 12/26/2010  satellit&lt;br /&gt;
# Very Slow -  Trisquel-3-sugar/VB 3.2.12 on Windows XP SP2/ EeePC 1000HE 12/26/2010  satellit&lt;br /&gt;
# Acceptable-  Fedora-13-Soas/VB 4.0 on Ubuntu 10.10 /hp Pavillion Turion 64x2 laptop  12/26/2010  satellit&lt;br /&gt;
# Acceptable-  Trisquel-3-sugar/VB 4.0 on Ubuntu 10.10 /hp Pavillion Turion 64x2 laptop  12/26/2010  satellit&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Join IRC for Help&#039;&#039;&#039;====&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar&amp;amp;prompt=1 Join Sugar chat room for Help in English]&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar-es&amp;amp;prompt=1 Sugar chat room in Español]&#039;&#039;&#039; (with translations to English)&lt;br /&gt;
 Pida ayuda a través de este canal #sugar-es Por favor, sea cortés y hacer sus preguntas.&lt;br /&gt;
 Los voluntarios no pueden estar en línea todo el tiempo.&lt;br /&gt;
 Sea paciente y permanecer conectado durante varios minutos para ver su respuest &lt;br /&gt;
:::(utilizar la función de meeting para la traducción de estos artículos)&lt;br /&gt;
&lt;br /&gt;
: Ask for help on either of these channels.&lt;br /&gt;
:: Please be courteous and ask your questions.&lt;br /&gt;
:: Volunteers may not be on line all of the time. Be patient and stay connected for several minutes to see their answer.&lt;br /&gt;
* &#039;&#039;&#039;Read the [[Sugar_Creation_Kit#Floss_Manuals| Floss Manuals]] first!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====References====&lt;br /&gt;
:http://www.virtualbox.org/manual/ch03.html#id2727661 [Configuring virtual machines]&lt;br /&gt;
:http://www.virtualbox.org/manual/ch03.html#id321700 [USB Support]&lt;br /&gt;
:[http://www.virtualbox.org/manual/ Oracle VM VirtualBox online Manual]&lt;br /&gt;
:[http://download.virtualbox.org/virtualbox/UserManual.pdf UserManual.pdf]&lt;br /&gt;
&lt;br /&gt;
====Extension Pack====&lt;br /&gt;
:[http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html Oracle VM VirtualBox Extension Pack]  &#039;&#039;&#039;Personal Use License&#039;&#039;&#039;&lt;br /&gt;
::All Platforms (Windows, Mac OS X, Solaris and Linux)&lt;br /&gt;
* &#039;&#039;&#039;Personal Use Licensed not OSE&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;[[VMware]] Player&#039;&#039;&#039;===&lt;br /&gt;
[https://www.vmware.com/tryvmware/?p=player&amp;amp;lp=default Download VMware Player (free)] &lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance of soas-v3-Mirabelle&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Soas-v3-Mirabelle.zip Download]&lt;br /&gt;
::This appliance is ready to run &amp;quot;firstboot&amp;quot; (agree/user name/password/tz/etc) &lt;br /&gt;
::&#039;&#039;&#039;sugarroot&#039;&#039;&#039; is the root password.&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-3 (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel3.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-4+sugar (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel-4-sugar-VMPlayer.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Sugar on a Stick v2 (Blueberry)&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.txt Read this first.]&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.tar.gz download]&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance of openSUSE-Sugar&lt;br /&gt;
:[[VMware#openSUSE |Read this first.]]&lt;br /&gt;
:[http://sourceforge.net/projects/opensuse-edu/files/Sugar/openSUSE-Sugar-vmware-vmx.tar.bz2/download download]&lt;br /&gt;
:[[Talk:VMware#change_networking|networking help]]&lt;br /&gt;
:[http://old-en.opensuse.org/How_to_use_downloaded_SUSE_Studio_appliances how to use]&lt;br /&gt;
&lt;br /&gt;
===Older Virtual Appliances===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hint for the following Appliances: when Downloading xxxx.mf and xxxx.ovf files use &amp;quot;save as&amp;quot; to download then hit &amp;lt; on browser to return to previous screen in browser&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Sugar on a Stick v2 Bluberry&#039;&#039;&#039; &lt;br /&gt;
:link:   [[Sugar on a Stick/Blueberry|Blueberry]]&amp;lt;br&amp;gt;[http://people.sugarlabs.org/Tgillard/soas-2-blueberry_ovf_README_FIRST.txt Read this first.]&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;: [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.ovf soas-2-blueberry.ovf] [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.mf soas-2-blueberry.mf]  [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.vmdk soas-2-blueberry.vmdk]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Sugar on a Stick v1 Strawberry&#039;&#039;&#039;&lt;br /&gt;
:Link:  [[Sugar on a Stick/Strawberry|Strawberry]]&lt;br /&gt;
: [http://www.sugarlabs.org/static/soas/soas-strawberry-vdi.zip soas-strawberry-vdi.zip] Sugar 0.84 (22 June 2009)&lt;br /&gt;
::This is a compressed VirtualBox Hardisk. Decompress it and Create a new VirtualBox Appliance that points to this &#039;&#039;&#039;existing .vdi Hard Disk&#039;&#039;&#039; not a new one.&lt;br /&gt;
::&#039;&#039;&#039;[http://wiki.sugarlabs.org/go/Talk:Emulator_image_files#How_to_Update_Soas-v1-Strawberry-vdi How_to_Update_Soas-v1-Strawberry-vdi Activities]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;openSUSE-Sugar-11.3&#039;&#039;&#039;&lt;br /&gt;
: Reference links:  [http://download.opensuse.org/repositories/Education/images/iso/openSUSE-Sugar-11.3.i686-1.0.0-Build6.3.iso openSUSE-Sugar-11.3.i686-1.0.0-Build6.3.iso] Uploaded 26 September 2010&amp;lt;br&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;:openSUSE_sugar.ovf [http://people.sugarlabs.org/Tgillard/openSUSE_sugar.ovf openSUSE_sugar.ovf] [http://people.sugarlabs.org/Tgillard/openSUSE_sugar.mf openSUSE_sugar.mf] [http://people.sugarlabs.org/Tgillard/openSUSE-Sugar-11.3.vmdk openSUSE-Sugar-11.3.vmdk]&lt;br /&gt;
::8-GB VirtualBox hard disc&lt;br /&gt;
::English and English keyboard&lt;br /&gt;
::USA-Los Angeles (Pacific timezone)&lt;br /&gt;
::Autologin- user=sugar password=sugaruser&lt;br /&gt;
:::Ready to auto-configure to your hardware on first booting.&lt;br /&gt;
:::&#039;&#039;&#039;note choose /dev/sda2 when prompted to do so on first run&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;U&#039;&#039;&#039;buntu&#039;&#039;&#039;S&#039;&#039;&#039;ugar&#039;&#039;&#039;&#039;&#039;R&#039;&#039;&#039;emix&#039;&#039;&lt;br /&gt;
: Reference links:  [[Community/Distributions/Ubuntu]], https://wiki.ubuntu.com/Sugar&lt;br /&gt;
::&#039;&#039;shutdown does nothing from sugar; To exit sugar use &amp;quot;Log Out&amp;quot; then shutdown from bottom right gdm bar&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;: [http://people.sugarlabs.org/Tgillard/USR-922-IRC-Remix.ovf USR-922-IRC-Remix.ovf] [http://people.sugarlabs.org/Tgillard/USR-922-IRC-Remix.mf USR-922-IRC-Remix.mf]  [http://people.sugarlabs.org/Tgillard/USR-i386-20100922.vmdk USR-i386-20100922.vmdk]&lt;br /&gt;
::TZ=LA USA USA Keyboard 8-GB HD fully updated on 22 September 2010 with&lt;br /&gt;
::apt-get Updates&lt;br /&gt;
::apt-get Upgrade&lt;br /&gt;
::Remixed to add&lt;br /&gt;
:::Surf-115.xo browser&lt;br /&gt;
:::IRC.xo -(edited to log in to #sugar and #ubuntu-sugarteam)&lt;br /&gt;
:::Analyze.xo&lt;br /&gt;
:::&#039;&#039;&#039;Import the 3 files into Oracle VirtualBox&#039;&#039;&#039;&lt;br /&gt;
::: User=sugar autologin&lt;br /&gt;
::: Password=sugaruser&lt;br /&gt;
*&#039;&#039;&#039;install the VirtualBox guest additions&#039;&#039;&#039;&lt;br /&gt;
::Integrates a Running VirtualBox Appliance with the desktop&lt;br /&gt;
:install the VirtualBox guest additions with &#039;&#039;sudo apt-get install virtualbox-ose-guest-utils&#039;&#039;&lt;br /&gt;
===&#039;&#039;&#039;[[QEMU]]&#039;&#039;&#039;===&lt;br /&gt;
:[[Sugar_Creation_Kit#QEMU_Virtualization|instructions, downloads]]&lt;br /&gt;
&lt;br /&gt;
== Image installation tools ==&lt;br /&gt;
===&#039;&#039;&#039;[[Sugar_on_a_Stick/ZyX-LiveInstaller|ZyX-LiveInstaller]]&#039;&#039;&#039;===&lt;br /&gt;
* ZyX-LiveInstaller allows you to install Sugar from either a booted Live USB device,&lt;br /&gt;
* or Live CD media to a system or external disk.&lt;br /&gt;
* It creates an exact copy of your running live CD as a traditional (Persistent) installation on your hard-disk (or removable media such as SD or USB storage devices.&lt;br /&gt;
: This program can be useful for installing to a virtualized hard disk. It is not included in builds after soas-v2 Blueberry, so it must be downloaded and installed to use.&lt;br /&gt;
: In a running SoaS Terminal session or console, execute the following commands:&lt;br /&gt;
: {{Code|su}} &lt;br /&gt;
: {{Code|yum install zyx-liveinstaller gparted}}&lt;br /&gt;
&lt;br /&gt;
===[http://www.easyvmx.com EasyVMX!]===&lt;br /&gt;
:&#039;&#039;&#039;Make a VirtualBox or VMware Player appliance with a burned CD of your favorite xxx.iso&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;http://www.easyvmx.com/ is a web site that builds a vmx file to your specifications (free).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: Works fine, runs on most platforms, and has persistence after installation. (tested with Trisquel 4.0.1 DVD 12/24/2010 satellit)&lt;br /&gt;
:: Virtual Appliance that you create Can be opened with either VirtualBox or VMware Player&lt;br /&gt;
: VirtualBox 4.0 Download (free): http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html&lt;br /&gt;
: VMware Player download (free): http://www.vmware.com/tryvmware/&lt;br /&gt;
:::(Note:VMware Workstation not needed for VMware Player to create Virtual Appliance)&lt;br /&gt;
&lt;br /&gt;
::specified a 8 GB Hard Drive; name; and other parameters&lt;br /&gt;
::downloaded, in browse, the Custom vmx file as a .zip file&lt;br /&gt;
::Decompressed the .zip file&lt;br /&gt;
&lt;br /&gt;
: Insert the CD of your favorite xxx.iso&lt;br /&gt;
&lt;br /&gt;
::Open VirtualBox4.0 or VMware Player and point it to this vmx file&lt;br /&gt;
:::In VirtualBox Settings/specify CD Player (/dev/sr0); Start&lt;br /&gt;
:::VMware Player starts CD automatically&lt;br /&gt;
&lt;br /&gt;
* EXAMPLE: soas-i386-20100926.17.iso burned to a CD&lt;br /&gt;
::Put soas-i386-20100926.17 CD in your CD Drive&lt;br /&gt;
::CD boots in VirtualBox-4.0 or VMware Player application&lt;br /&gt;
::Sugar Starts&lt;br /&gt;
&lt;br /&gt;
*To install to EasyVMX Hard Disk:&lt;br /&gt;
:Open Sugar-terminal:&lt;br /&gt;
 su&lt;br /&gt;
 liveinst&lt;br /&gt;
 Anaconda installer opens&lt;br /&gt;
 Initialize all disks&lt;br /&gt;
 Install procedes normally&lt;br /&gt;
 reboot&lt;br /&gt;
 firstboot&lt;br /&gt;
 Log in to user you specified&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HINT: copy all of the EasyVMX Hard Disk Files on a 2 GB USB stick.&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;(note runs about 10x slower on a USB stick)&#039;&#039;&#039;&lt;br /&gt;
::Example above created a 1.4 GB set of files&#039;&lt;br /&gt;
:Copy-Paste all files&lt;br /&gt;
: Sugar on a Stick in VirtualBox or VMware Player Hard Disk format with persistence&lt;br /&gt;
::Portable (Student can take home and run on home Computer)&lt;br /&gt;
::Run it on different Platforms&lt;br /&gt;
&lt;br /&gt;
==Click for: [[Talk:Emulator image files|More Discussions]]==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Mac OS X-Boot USB with VirtualBox]]&lt;br /&gt;
* [http://lists.laptop.org/pipermail/devel/2008-September/019643.html Tom van Overbeek describes how to run Sugar using QEMU]&lt;br /&gt;
* [https://fedoraproject.org/wiki/Features/BoxGrinder BoxGrinder: a set of tools used for building appliances (virtual machines)]&lt;br /&gt;
* [http://fedoraproject.org/wiki/Licensing Licensing-License types and info for exported Appliances-]&lt;br /&gt;
&lt;br /&gt;
== Thanks ==&lt;br /&gt;
&lt;br /&gt;
Thanks for this work satellit_, emulators are a great way to develop and test stuff. --[[User:RafaelOrtiz|RafaelOrtiz]] 17:19, 13 April 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Emulator_image_files&amp;diff=65739</id>
		<title>Emulator image files</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Emulator_image_files&amp;diff=65739"/>
		<updated>2011-05-16T15:18:42Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* VirtualBox */ fix command to reset sugar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Virtual machine or platform emulator]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other virtual machines==&lt;br /&gt;
&lt;br /&gt;
This is a quick guide to the locations of various forms of Sugar software that can run in QEMU emulation or VMware or VirtualBox virtualization.&lt;br /&gt;
&lt;br /&gt;
You can download installation images (.iso files) for Linux distributions that support Sugar and create your own bootable images with Sugar installed.&lt;br /&gt;
&lt;br /&gt;
See [[VirtualBox]], [[VMware]], or [[QEMU]] for more information on how to run an image, and [[Supported systems]] for more information on what is available.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
       This page is meant to be a brief index to recommended, downloadable images--not a discussion page for their use or features.  For experimental images, please refer readers to the appropriate software page elsewhere.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:wikipedia: &#039;&#039;&#039;[[wikipedia:Comparison_of_platform_virtual_machines|Comparison of platform virtual machines]]&#039;&#039;&#039; - Very nice comparison of features of Virtual Machines platforms&lt;br /&gt;
===[[File:VirtualBox.png|75px|link=VirtualBox]]&#039;&#039;&#039;[[VirtualBox]]&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
Latest version: &#039;&#039;&#039;VirtualBox 4.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Download: http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html&lt;br /&gt;
:&#039;&#039;Preliminary testing shows that VirtualBox Appliances from ver 3.1.10-12 import and function well in ver 4.0.x and visa-versa.&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
* VirtualBox-4.0 is OSE version until you add: [http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html Oracle VM VirtualBox Extension Pack]&lt;br /&gt;
* Support for Windows, Mac OS X, Solaris, and GNU/Linux&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VMware Workstation xxx.vmdk Hard Disks will work as &amp;quot;existing Disks&amp;quot; in VirtualBox&#039;&#039;&#039;&lt;br /&gt;
* [http://www.virtualbox.org/manual/ VirtualBox Manual]&lt;br /&gt;
* [http://www.virtualbox.org/manual/ch08.html VBoxManage command line tool for VirtualBox] for advanced users&lt;br /&gt;
{{Admon/note|&lt;br /&gt;
* &#039;&#039;&#039;When making a new VM&#039;&#039;&#039;, to clear the Sugar Journal of old entries and to avoid identity conflicts among copies of the VM, enter the command {{Code|rm&amp;amp;nbsp;-rf&amp;amp;nbsp;~/.sugar}} in the Terminal activity. Then shutdown the VM. This will clear all Learner information on the VM and let you start with a fresh install. Skipping this will result in collisions in the Neighborhood view of the Jabber network between separate copies of the appliance. Verify the presence of the &#039;&#039;&#039;.sugar&#039;&#039;&#039; directory by entering {{Code|ls&amp;amp;nbsp;-a}} in Terminal.&lt;br /&gt;
* &#039;&#039;&#039;When cloning a customized VM&#039;&#039;&#039;, in order to keep the Journal and installed .xo Activities, use {{Code|rm&amp;amp;nbsp;~/.sugar/default/owner.key*}} in the Sugar Terminal, and then shutdown the VM. This leaves the Journal entries and removes only the previous Learner&#039;s identity key files.}}&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v3 Mirabelle&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;Sugar 0.88.0&#039;&#039;&#039;&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
::firstboot has not yet run; so a new user name and password will be set for the gdm login on startup for the first time&lt;br /&gt;
:How Built:&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
: 8-GB Virtual Box hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.vmdk 533M&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.ovf   12K&lt;br /&gt;
&lt;br /&gt;
*Note1:Use a later version of Oracle VM VirtualBox (3.2_10.8-64453 or later). Some appliances have multiple hard disc controllers and the earlier Sun VirtualBox 3.1 version does not support them.&lt;br /&gt;
*Note2: All appliances were built on a MacBook Air with Oracle VM VirtualBox (3.2.10-r66523) then tested on a Ubuntu installation on an Acer Aspire One Netbook imported into VirtualBox (3.2.10 r66523)&lt;br /&gt;
*Note3:Set ControlPanel/Frame &amp;quot;Edge&amp;quot; slider to far left for easier access to sugar-frame features&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;VMware Player Version&#039;&#039;&#039;&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Soas-v3-Mirabelle.zip Soas-v3-Mirabelle.zip Download]&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v4 Mango Lassi&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;Sugar 0.90.1&#039;&#039;&#039; &#039;&#039;Note Sugar 0.90.x is buggy, use a version of SoaS with the 0.88.1 version.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:user=sugar&lt;br /&gt;
:password=sugaruser&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
:How Built:&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-14-i686-Live-SoaS-2.ovf 12K&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-14-i686-Live-SoaS-2-disk1.vmdk  606M&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;had to modify the .ovf to get the image running on a X60 with ubuntu maverick:&#039;&#039;&#039;&lt;br /&gt;
 http://people.sugarlabs.org/dogi/virtualbox/Fedora-14-i686-Live-SoaS-2.1.ovf 12K&lt;br /&gt;
&lt;br /&gt;
*Note, this appliance has 1024x768 screensize available as VirtualBox extensions were compiled into the kernel.&lt;br /&gt;
&lt;br /&gt;
=====To Update Sugar=====&lt;br /&gt;
:Sugar update does not work in control panel&lt;br /&gt;
* In root sugar-terminal:&lt;br /&gt;
 yum groupinstall sugar-desktop&lt;br /&gt;
: (install 9 packages, Upgrade 10 packages) 02/02/2011 satellit&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]&#039;&#039;&#039;Sugar on a Stick v5 Coconut&#039;&#039;&#039;====&lt;br /&gt;
:&#039;&#039;&#039;sugar 0.92.1&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;this is the RC3 version; for testing only at this time&#039;&#039;&#039;&lt;br /&gt;
:http://alt.fedoraproject.org/pub/alt/stage/15.RC3/Live/i686/Fedora-15-i686-Live-SoaS.iso&lt;br /&gt;
:user=sugar&lt;br /&gt;
:password=sugaruser&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
:How Built:&lt;br /&gt;
:liveinst in root terminal to VirtualBox HD&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;Cleared of Identity- starts at click to change color after gdm login&#039;&#039;&#039;&lt;br /&gt;
::Etoys fixed so it starts&lt;br /&gt;
::sub-menus work on activities&lt;br /&gt;
::Jabber fills up with duplicate avitars that constantly change colors en-mass.&lt;br /&gt;
::http://bugs.sugarlabs.org/ticket/2845&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Soas-v5_RC3_Live_CE.ovf  12.5KB&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Soas-v5_RC3_Live_CE-disk1.vmdk  621 MB&lt;br /&gt;
&lt;br /&gt;
====f15-Gnome3-Ver3.0.0-Virtual Box-Appliance====&lt;br /&gt;
*download these 2 files and import them:&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/F15-gnome3_Desktop_sugar_cl-disk1.vmdk&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/F15-gnome3_Desktop_sugar_cl.ovf&lt;br /&gt;
; Starts in gnome3 fallback mode as VirtualBox does not support hardware acceleration&lt;br /&gt;
::user=sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
:Cleared of sugar identity&#039; starts on select color by clicking on XO icon&lt;br /&gt;
:use &amp;lt;== arrow to write your custom name then ==&amp;gt; to finish&lt;br /&gt;
*Sugar-emulator is in Activities/Education/Sugar&lt;br /&gt;
:::enter user password for keychain (sugaruser) on time and cancel until pop-up finishes (this is a bug in keychain in f15)&lt;br /&gt;
:Surf-115 is the browser as Browse-120 does not start (known bug)&lt;br /&gt;
&lt;br /&gt;
====f14-SoaS====&lt;br /&gt;
*download these 2 files and import them:&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/Fedora_14_SoaS.ovf&lt;br /&gt;
:http://people.sugarlabs.org/Tgillard/Fedora_14_SoaS-disk1.vmdk&lt;br /&gt;
::user=sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
*firstboot has not yet been run.&lt;br /&gt;
:Sugar on a Stick 4 (Mango Lassi)&lt;br /&gt;
:sugar: 0.90.1&lt;br /&gt;
*Bugs:&lt;br /&gt;
:: Control Panel/Software Update does not work.&lt;br /&gt;
:: Delay in start (edit to uncheck floppy disk)&lt;br /&gt;
&lt;br /&gt;
====[[File:trisquel_logo.png]][http://people.sugarlabs.org/Tgillard/Trisquel41_sugar_installer.iso Trisquel41_sugar_installer.iso]====&lt;br /&gt;
:Revised 03/02/2011 to remove sugar identity&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
*click above link^ to download 1.2GB  DVD which contains&lt;br /&gt;
 32bit-VirtualBox Installers (OSE) (Directory with install files for VirtualBox 4.0.4)&lt;br /&gt;
 (Does not include Free for Personal Use licensed extension pack) - includes instructions on how to download for personal use.&lt;br /&gt;
 ReadMeFirst_Install_Instructions.pdf  (Instructions-how to install VirtualBox and import appliance)&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18.ovf&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18-disk1.vmdk&lt;br /&gt;
 UserManual.pdf (VirtualBox 4.0.4 User Manual-269 pages)&lt;br /&gt;
: Instructions and .vmdk/.ovf files to import&lt;br /&gt;
* Cleared of sugar identity Starts on Color Selection Screen ( &amp;lt;===(back) to change name)&lt;br /&gt;
{{Admon/faq|Question|Does this contain Oracle VirtualBox binaries that are not redistributable under their [http://www.virtualbox.org/wiki/Licensing_FAQ licensing]?&amp;lt;br&amp;gt;We may need their permission to redistribute some of their software.  see listing above of contents for answer}}&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]] Trisquel-Gnome-sugar 4.5 Release Candidate====&lt;br /&gt;
::[http://devel2.trisquel.info/slaine/iso/ trisquel 4.5 Download]&lt;br /&gt;
: XChat; sweets-sugar 0.88.1; surf115-xo; updated; cleared of identity; autostart &lt;br /&gt;
::User=sugar&lt;br /&gt;
::password sugaruser&lt;br /&gt;
*&amp;quot;Free Distibution&amp;quot;&lt;br /&gt;
*Ubuntu 10.10 based&lt;br /&gt;
* Trisquel 4.5 RC VirtualBox 4.0.4 appliance &lt;br /&gt;
:Download and Import these files:&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/trisquel_4.5-RC_i686surf115-cleared.ovf&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/trisquel_4.5-RC_i686surf115-cleared-disk1.vmdk&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.5 -Gnome-sugar BETA|Trisquel-4.5 -Gnome-sugar BETA]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Gnome and Sugar 0.88.1&lt;br /&gt;
*: Beta, so not for Production use, but quite stable for testing&lt;br /&gt;
* [http://devel2.trisquel.info/slaine/iso/ Trisquel 4.5 Download]&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* Sugar sweets 0.88.1 with 30 applications:  [[Trisquel_On_A_Sugar_Toast#Install_Sugar-desktop_0.88_.22SWEETS.22|How to install sweets-sugar-desktop 0.88.1]]&lt;br /&gt;
*: Updated 02/04/2011 (System/Administration/Update Manager)&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/Tris-45-Sugar0801-4.ovf           13K&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/Tris-45-Sugar0801-4-disk1.vmdk   1.4G  &lt;br /&gt;
&lt;br /&gt;
*NOTE: This is a Beta version.  A lot of updates are still coming in.&lt;br /&gt;
*: Sugar 0.88.1 is a much more stable release than sugar 0.90.1&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.1-sugar|Trisquel-4.1-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
* Sugar sweets 0.88.1&lt;br /&gt;
*:NEW: 02/18/2011 2nd Beta Version with application fixes&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned-disk1.vmdk&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned.ovf&lt;br /&gt;
&lt;br /&gt;
* Cleared of sugar identity Starts on Color Selection Screen ( &amp;lt;===(back) to change name) 03/02/2011&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-4.0.1-Gnome-sugar|Trisquel-4.0.1-Gnome-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Gnome and Sugar 0.90.1&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* Updated 12/23/2010&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/trisquel_4.0.1_ext4-sugar0901.ovf 13K&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/trisquel_4.0.1_ext4.vmdk 2.1 GB&lt;br /&gt;
&lt;br /&gt;
* VMware Player Version&lt;br /&gt;
*:[http://download.sugarlabs.org/images/vmplayer/Trisquel-4-sugar-VMPlayer.zip Trisquel-4-sugar-VMPlayer Download]&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][[/Trisquel#Trisquel-3-sugar|Trisquel-3-sugar]]====&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
* Sugar 0.86.2&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/Trisquel-3-sugar-sugaruser.vmdk 543M&lt;br /&gt;
*# http://download.sugarlabs.org/images/VirtualBox/Trisquel-3-sugar-sugaruser.ovf   12K&lt;br /&gt;
&lt;br /&gt;
* VMware Player Version&lt;br /&gt;
*:[http://download.sugarlabs.org/images/vmplayer/Trisquel3.zip Trisquel3.zip Download]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;20 new applications were installed by CP/software update&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====[[Image:Debian-small.jpg]]&#039;&#039;&#039;Debian-squeeze-Gnome-sugar&#039;&#039;&#039;====&lt;br /&gt;
::&#039;&#039;&#039;Full Gnome Desktop plus Sugar 0.88.1&#039;&#039;&#039;&lt;br /&gt;
::[http://wiki.sugarlabs.org/go/Community/Distributions/Debian Debian Information]&lt;br /&gt;
:Updated 12/05/2010 includes activities Downloaded from ASLO as .xo files; and sugar-emulator.&lt;br /&gt;
::Log in as sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugarroot&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Debian-sugaruser.vmdk  2.1G&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Debian-sugaruser-1.ovf 14K&lt;br /&gt;
&lt;br /&gt;
====[[Image:Mandriva-small.png]]&#039;&#039;&#039;Mandriva-linux-one-2010.1-Gnome-sugar&#039;&#039;&#039;====&lt;br /&gt;
::&#039;&#039;&#039;Full Gnome Desktop plus Sugar-0.88.0&#039;&#039;&#039;&lt;br /&gt;
::[http://wiki.sugarlabs.org/go/Community/Distributions/Mandriva Mandriva Information]&lt;br /&gt;
:::Note Log into gnome desktop first to enable networking then start sugar-emulator &lt;br /&gt;
::Log in as sugar&lt;br /&gt;
::password=sugaruser&lt;br /&gt;
::root=sugaruser&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
  download and import 2 files:&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/mandriva-linux-one-2010-sugaruser-plus.ovf  14K &lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/mandriva-linux-one-2010.vmdk  1.4G&lt;br /&gt;
&lt;br /&gt;
Info:&lt;br /&gt;
: [http://www2.mandriva.com/downloads/free/ 2010.2 free DVD Download]&lt;br /&gt;
: [http://wiki.mandriva.com/en/Mandriva_Linux_2010.1 Mandriva_Linux_2010.1 Download]&lt;br /&gt;
: [http://www2.mandriva.com/en/linux/overview/ Mandriva 2010.1 Features]&lt;br /&gt;
: [http://www2.mandriva.com/en/news/?p=145&amp;amp;s=0 The Brazilian government education authority has selected Intel-powered classmate PCs running Mandriva Linux for educational use nationwide.]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[:File:MacBook_Air-Virtualbox.jpg|Photo of Neighborhood view on MacBook Air-Mandriva 2010.1]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Note: The above appliances were built on a MacBook Air with Oracle VM VirtualBox (3.2.10-r66523) then tested on a Ubuntu installation on an Acer Aspire One Netbook imported into VirtualBox (3.2.10 r66523)&lt;br /&gt;
&lt;br /&gt;
====Some Suggestions on Using VirtualBox====&lt;br /&gt;
* Export your appliances to an external USB hard disk&lt;br /&gt;
*: This functions like the Mac Application &amp;quot;Time Machine&amp;quot;&lt;br /&gt;
*: Save each exported Appliance in a folder marked with the name and date of export.&lt;br /&gt;
*::You can then import this Appliance to restore the state of the Appliance on that date.&lt;br /&gt;
&lt;br /&gt;
*Run an Existing VirtualBox Appliance from an external USB Hard Drive&lt;br /&gt;
*::Portable, Individual Copy for Student, Move between separate Computers.&lt;br /&gt;
*# copy-paste the xxxx.vmdk file from /(User)/Virtualbox/HardDisks/xxxx.vmdk to a Folder on an external USB HD&lt;br /&gt;
*# Menu: Machine&amp;gt;New&amp;gt;continue&amp;gt;Name&amp;gt;Operating System&amp;gt;Version/Memory/Continue&amp;gt;Use existing hard disk&amp;gt;[chose xxxx.vmdk on an External USB HD]&amp;gt; Start.&lt;br /&gt;
&lt;br /&gt;
* Note Running from a USB Memory Stick Crawls, VERY slowly - &#039;&#039;&#039;not practical&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Testing of appliance running from an external USB Hard Disk&lt;br /&gt;
:: Appears to depend on the Speed of the Host Machine: (needs farther testing)&lt;br /&gt;
# Very Slow -  Fedora-13-Soas/VB 3.2.12 on Windows XP SP2/ EeePC 1000HE 12/26/2010  satellit&lt;br /&gt;
# Very Slow -  Trisquel-3-sugar/VB 3.2.12 on Windows XP SP2/ EeePC 1000HE 12/26/2010  satellit&lt;br /&gt;
# Acceptable-  Fedora-13-Soas/VB 4.0 on Ubuntu 10.10 /hp Pavillion Turion 64x2 laptop  12/26/2010  satellit&lt;br /&gt;
# Acceptable-  Trisquel-3-sugar/VB 4.0 on Ubuntu 10.10 /hp Pavillion Turion 64x2 laptop  12/26/2010  satellit&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Join IRC for Help&#039;&#039;&#039;====&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar&amp;amp;prompt=1 Join Sugar chat room for Help in English]&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar-es&amp;amp;prompt=1 Sugar chat room in Español]&#039;&#039;&#039; (with translations to English)&lt;br /&gt;
 Pida ayuda a través de este canal #sugar-es Por favor, sea cortés y hacer sus preguntas.&lt;br /&gt;
 Los voluntarios no pueden estar en línea todo el tiempo.&lt;br /&gt;
 Sea paciente y permanecer conectado durante varios minutos para ver su respuest &lt;br /&gt;
:::(utilizar la función de meeting para la traducción de estos artículos)&lt;br /&gt;
&lt;br /&gt;
: Ask for help on either of these channels.&lt;br /&gt;
:: Please be courteous and ask your questions.&lt;br /&gt;
:: Volunteers may not be on line all of the time. Be patient and stay connected for several minutes to see their answer.&lt;br /&gt;
* &#039;&#039;&#039;Read the [[Sugar_Creation_Kit#Floss_Manuals| Floss Manuals]] first!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====References====&lt;br /&gt;
:http://www.virtualbox.org/manual/ch03.html#id2727661 [Configuring virtual machines]&lt;br /&gt;
:http://www.virtualbox.org/manual/ch03.html#id321700 [USB Support]&lt;br /&gt;
:[http://www.virtualbox.org/manual/ Oracle VM VirtualBox online Manual]&lt;br /&gt;
:[http://download.virtualbox.org/virtualbox/UserManual.pdf UserManual.pdf]&lt;br /&gt;
&lt;br /&gt;
====Extension Pack====&lt;br /&gt;
:[http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html Oracle VM VirtualBox Extension Pack]  &#039;&#039;&#039;Personal Use License&#039;&#039;&#039;&lt;br /&gt;
::All Platforms (Windows, Mac OS X, Solaris and Linux)&lt;br /&gt;
* &#039;&#039;&#039;Personal Use Licensed not OSE&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;[[VMware]] Player&#039;&#039;&#039;===&lt;br /&gt;
[https://www.vmware.com/tryvmware/?p=player&amp;amp;lp=default Download VMware Player (free)] &lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance of soas-v3-Mirabelle&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Soas-v3-Mirabelle.zip Download]&lt;br /&gt;
::This appliance is ready to run &amp;quot;firstboot&amp;quot; (agree/user name/password/tz/etc) &lt;br /&gt;
::&#039;&#039;&#039;sugarroot&#039;&#039;&#039; is the root password.&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-3 (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel3.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-4+sugar (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel-4-sugar-VMPlayer.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Sugar on a Stick v2 (Blueberry)&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.txt Read this first.]&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.tar.gz download]&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance of openSUSE-Sugar&lt;br /&gt;
:[[VMware#openSUSE |Read this first.]]&lt;br /&gt;
:[http://sourceforge.net/projects/opensuse-edu/files/Sugar/openSUSE-Sugar-vmware-vmx.tar.bz2/download download]&lt;br /&gt;
:[[Talk:VMware#change_networking|networking help]]&lt;br /&gt;
:[http://old-en.opensuse.org/How_to_use_downloaded_SUSE_Studio_appliances how to use]&lt;br /&gt;
&lt;br /&gt;
===Older Virtual Appliances===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hint for the following Appliances: when Downloading xxxx.mf and xxxx.ovf files use &amp;quot;save as&amp;quot; to download then hit &amp;lt; on browser to return to previous screen in browser&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Sugar on a Stick v2 Bluberry&#039;&#039;&#039; &lt;br /&gt;
:link:   [[Sugar on a Stick/Blueberry|Blueberry]]&amp;lt;br&amp;gt;[http://people.sugarlabs.org/Tgillard/soas-2-blueberry_ovf_README_FIRST.txt Read this first.]&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;: [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.ovf soas-2-blueberry.ovf] [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.mf soas-2-blueberry.mf]  [http://people.sugarlabs.org/Tgillard/soas-2-blueberry.vmdk soas-2-blueberry.vmdk]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Sugar on a Stick v1 Strawberry&#039;&#039;&#039;&lt;br /&gt;
:Link:  [[Sugar on a Stick/Strawberry|Strawberry]]&lt;br /&gt;
: [http://www.sugarlabs.org/static/soas/soas-strawberry-vdi.zip soas-strawberry-vdi.zip] Sugar 0.84 (22 June 2009)&lt;br /&gt;
::This is a compressed VirtualBox Hardisk. Decompress it and Create a new VirtualBox Appliance that points to this &#039;&#039;&#039;existing .vdi Hard Disk&#039;&#039;&#039; not a new one.&lt;br /&gt;
::&#039;&#039;&#039;[http://wiki.sugarlabs.org/go/Talk:Emulator_image_files#How_to_Update_Soas-v1-Strawberry-vdi How_to_Update_Soas-v1-Strawberry-vdi Activities]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;openSUSE-Sugar-11.3&#039;&#039;&#039;&lt;br /&gt;
: Reference links:  [http://download.opensuse.org/repositories/Education/images/iso/openSUSE-Sugar-11.3.i686-1.0.0-Build6.3.iso openSUSE-Sugar-11.3.i686-1.0.0-Build6.3.iso] Uploaded 26 September 2010&amp;lt;br&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;:openSUSE_sugar.ovf [http://people.sugarlabs.org/Tgillard/openSUSE_sugar.ovf openSUSE_sugar.ovf] [http://people.sugarlabs.org/Tgillard/openSUSE_sugar.mf openSUSE_sugar.mf] [http://people.sugarlabs.org/Tgillard/openSUSE-Sugar-11.3.vmdk openSUSE-Sugar-11.3.vmdk]&lt;br /&gt;
::8-GB VirtualBox hard disc&lt;br /&gt;
::English and English keyboard&lt;br /&gt;
::USA-Los Angeles (Pacific timezone)&lt;br /&gt;
::Autologin- user=sugar password=sugaruser&lt;br /&gt;
:::Ready to auto-configure to your hardware on first booting.&lt;br /&gt;
:::&#039;&#039;&#039;note choose /dev/sda2 when prompted to do so on first run&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;U&#039;&#039;&#039;buntu&#039;&#039;&#039;S&#039;&#039;&#039;ugar&#039;&#039;&#039;&#039;&#039;R&#039;&#039;&#039;emix&#039;&#039;&lt;br /&gt;
: Reference links:  [[Community/Distributions/Ubuntu]], https://wiki.ubuntu.com/Sugar&lt;br /&gt;
::&#039;&#039;shutdown does nothing from sugar; To exit sugar use &amp;quot;Log Out&amp;quot; then shutdown from bottom right gdm bar&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;download and import 3 files&#039;&#039;&#039;: [http://people.sugarlabs.org/Tgillard/USR-922-IRC-Remix.ovf USR-922-IRC-Remix.ovf] [http://people.sugarlabs.org/Tgillard/USR-922-IRC-Remix.mf USR-922-IRC-Remix.mf]  [http://people.sugarlabs.org/Tgillard/USR-i386-20100922.vmdk USR-i386-20100922.vmdk]&lt;br /&gt;
::TZ=LA USA USA Keyboard 8-GB HD fully updated on 22 September 2010 with&lt;br /&gt;
::apt-get Updates&lt;br /&gt;
::apt-get Upgrade&lt;br /&gt;
::Remixed to add&lt;br /&gt;
:::Surf-115.xo browser&lt;br /&gt;
:::IRC.xo -(edited to log in to #sugar and #ubuntu-sugarteam)&lt;br /&gt;
:::Analyze.xo&lt;br /&gt;
:::&#039;&#039;&#039;Import the 3 files into Oracle VirtualBox&#039;&#039;&#039;&lt;br /&gt;
::: User=sugar autologin&lt;br /&gt;
::: Password=sugaruser&lt;br /&gt;
*&#039;&#039;&#039;install the VirtualBox guest additions&#039;&#039;&#039;&lt;br /&gt;
::Integrates a Running VirtualBox Appliance with the desktop&lt;br /&gt;
:install the VirtualBox guest additions with &#039;&#039;sudo apt-get install virtualbox-ose-guest-utils&#039;&#039;&lt;br /&gt;
===&#039;&#039;&#039;[[QEMU]]&#039;&#039;&#039;===&lt;br /&gt;
:[[Sugar_Creation_Kit#QEMU_Virtualization|instructions, downloads]]&lt;br /&gt;
&lt;br /&gt;
== Image installation tools ==&lt;br /&gt;
===&#039;&#039;&#039;[[Sugar_on_a_Stick/ZyX-LiveInstaller|ZyX-LiveInstaller]]&#039;&#039;&#039;===&lt;br /&gt;
* ZyX-LiveInstaller allows you to install Sugar from either a booted Live USB device,&lt;br /&gt;
* or Live CD media to a system or external disk.&lt;br /&gt;
* It creates an exact copy of your running live CD as a traditional (Persistent) installation on your hard-disk (or removable media such as SD or USB storage devices.&lt;br /&gt;
: This program can be useful for installing to a virtualized hard disk. It is not included in builds after soas-v2 Blueberry, so it must be downloaded and installed to use.&lt;br /&gt;
: In a running SoaS Terminal session or console, execute the following commands:&lt;br /&gt;
: {{Code|su}} &lt;br /&gt;
: {{Code|yum install zyx-liveinstaller gparted}}&lt;br /&gt;
&lt;br /&gt;
===[http://www.easyvmx.com EasyVMX!]===&lt;br /&gt;
:&#039;&#039;&#039;Make a VirtualBox or VMware Player appliance with a burned CD of your favorite xxx.iso&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;http://www.easyvmx.com/ is a web site that builds a vmx file to your specifications (free).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
: Works fine, runs on most platforms, and has persistence after installation. (tested with Trisquel 4.0.1 DVD 12/24/2010 satellit)&lt;br /&gt;
:: Virtual Appliance that you create Can be opened with either VirtualBox or VMware Player&lt;br /&gt;
: VirtualBox 4.0 Download (free): http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html&lt;br /&gt;
: VMware Player download (free): http://www.vmware.com/tryvmware/&lt;br /&gt;
:::(Note:VMware Workstation not needed for VMware Player to create Virtual Appliance)&lt;br /&gt;
&lt;br /&gt;
::specified a 8 GB Hard Drive; name; and other parameters&lt;br /&gt;
::downloaded, in browse, the Custom vmx file as a .zip file&lt;br /&gt;
::Decompressed the .zip file&lt;br /&gt;
&lt;br /&gt;
: Insert the CD of your favorite xxx.iso&lt;br /&gt;
&lt;br /&gt;
::Open VirtualBox4.0 or VMware Player and point it to this vmx file&lt;br /&gt;
:::In VirtualBox Settings/specify CD Player (/dev/sr0); Start&lt;br /&gt;
:::VMware Player starts CD automatically&lt;br /&gt;
&lt;br /&gt;
* EXAMPLE: soas-i386-20100926.17.iso burned to a CD&lt;br /&gt;
::Put soas-i386-20100926.17 CD in your CD Drive&lt;br /&gt;
::CD boots in VirtualBox-4.0 or VMware Player application&lt;br /&gt;
::Sugar Starts&lt;br /&gt;
&lt;br /&gt;
*To install to EasyVMX Hard Disk:&lt;br /&gt;
:Open Sugar-terminal:&lt;br /&gt;
 su&lt;br /&gt;
 liveinst&lt;br /&gt;
 Anaconda installer opens&lt;br /&gt;
 Initialize all disks&lt;br /&gt;
 Install procedes normally&lt;br /&gt;
 reboot&lt;br /&gt;
 firstboot&lt;br /&gt;
 Log in to user you specified&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HINT: copy all of the EasyVMX Hard Disk Files on a 2 GB USB stick.&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;(note runs about 10x slower on a USB stick)&#039;&#039;&#039;&lt;br /&gt;
::Example above created a 1.4 GB set of files&#039;&lt;br /&gt;
:Copy-Paste all files&lt;br /&gt;
: Sugar on a Stick in VirtualBox or VMware Player Hard Disk format with persistence&lt;br /&gt;
::Portable (Student can take home and run on home Computer)&lt;br /&gt;
::Run it on different Platforms&lt;br /&gt;
&lt;br /&gt;
==Click for: [[Talk:Emulator image files|More Discussions]]==&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Mac OS X-Boot USB with VirtualBox]]&lt;br /&gt;
* [http://lists.laptop.org/pipermail/devel/2008-September/019643.html Tom van Overbeek describes how to run Sugar using QEMU]&lt;br /&gt;
* [https://fedoraproject.org/wiki/Features/BoxGrinder BoxGrinder: a set of tools used for building appliances (virtual machines)]&lt;br /&gt;
* [http://fedoraproject.org/wiki/Licensing Licensing-License types and info for exported Appliances-]&lt;br /&gt;
&lt;br /&gt;
== Thanks ==&lt;br /&gt;
&lt;br /&gt;
Thanks for this work satellit_, emulators are a great way to develop and test stuff. --[[User:RafaelOrtiz|RafaelOrtiz]] 17:19, 13 April 2011 (EDT)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Sugar_Creation_Kit&amp;diff=65707</id>
		<title>Sugar Creation Kit</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Sugar_Creation_Kit&amp;diff=65707"/>
		<updated>2011-05-15T17:55:07Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys-116 Soasv5 RC3 Error Fix */ formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Live USB]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sugar Creation Kit DVD==&lt;br /&gt;
[[File:Sugar Creation Kit.png]]&lt;br /&gt;
&amp;lt;span class=&amp;quot;linkgroup&amp;quot;&amp;gt;[[File:Download Mirabell.png|left|link=http://download.sugarlabs.org/images/SugarCreationKit-123.iso]]&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Caution, this is a large file, at 3.8 GB&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:A complete DVD containing all the resources required to create all 3 versions of Sugar-on-a-Stick without requiring Internet access.&lt;br /&gt;
&lt;br /&gt;
*[http://download.sugarlabs.org/images/SugarCreationKit-123.md5 SugarCreationKit-123.md5]&lt;br /&gt;
*[http://download.sugarlabs.org/images/SugarCreationKit1.2.3-Contents.txt List of Contents]&lt;br /&gt;
&lt;br /&gt;
Uses:&lt;br /&gt;
*&amp;quot;sneakernet&amp;quot; or behind firewall at school. &lt;br /&gt;
*save bandwidth on servers.&lt;br /&gt;
*download once and distribute copies locally.&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;&#039;[http://www.sugarlabs.org/ Sugar]&#039;&#039;&#039;==&lt;br /&gt;
;Click this^ link&lt;br /&gt;
:http://www.sugarlabs.org/&lt;br /&gt;
* Main sugarlabs introductory page&lt;br /&gt;
&lt;br /&gt;
=== &#039;&#039;&#039;[[Downloads | Get Sugar ]]&#039;&#039;&#039; ===&lt;br /&gt;
;Click this^ link&lt;br /&gt;
* Main Page to Download Sugar&lt;br /&gt;
&lt;br /&gt;
==[http://chat.sugarlabs.org:9090/?channels=sugar Chat login with list of Channels and languages]==&lt;br /&gt;
;Click this^ link to enter chat&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar&amp;amp;prompt=1 Join Sugar chat room for Help in English]&#039;&#039;&#039;  (with translations to Spanish on #sugar-es)&lt;br /&gt;
*&#039;&#039;&#039;[http://webchat.freenode.net/?randomnick=1&amp;amp;channels=sugar-es&amp;amp;prompt=1 Sugar chat room in Español]&#039;&#039;&#039;  (con traducción al Inglés de #sugar)&lt;br /&gt;
 Pida ayuda a través de este canal #sugar-es Por favor, sea cortés y hacer sus preguntas.&lt;br /&gt;
 Los voluntarios no pueden estar en línea todo el tiempo.&lt;br /&gt;
 Sea paciente y permanecer conectado durante varios minutos para ver su respuest &lt;br /&gt;
:::(utilizar la función de meeting para la traducción de estos artículos)&lt;br /&gt;
* Ask for help on these IRC channels by clicking on either of the above links (English or Spanish)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;NOTE: there are 4 channels on IRC: #sugar; #sugar-es; #sugar-it; #sugar-de&#039;&#039;&#039;&lt;br /&gt;
::these channels which use MEETING to do translations between them.&lt;br /&gt;
::to join enter this in command line of IRC: &#039;&#039;&#039;/join #sugar-it&#039;&#039;&#039; ;  &#039;&#039;&#039;/join #sugar-de&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;big&amp;gt;&amp;lt;big&amp;gt;Please be courteous and ask your questions.&amp;lt;/big&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
::&amp;lt;big&amp;gt;&amp;lt;big&amp;gt; Volunteers may not be on line all of the time. Be patient and stay connected for several minutes to see their answer.&amp;lt;/big&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;&amp;lt;big&amp;gt;&#039;&#039;&#039;Read the [[Sugar_Creation_Kit#Floss_Manuals| Floss Manuals]] first!&#039;&#039;&#039;&amp;lt;/big&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
:: Most answers can be found in them&lt;br /&gt;
&lt;br /&gt;
*More about [http://wiki.sugarlabs.org/go/Internet_Relay_Chat Internet_Relay_Chat]&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039;[[Sugar_Labs/Communication_channels|Communication channels]]&#039;&#039;&#039;===&lt;br /&gt;
;Click this ^ link to access a page with all the means to communicate with Sugar Labs contributors and learners. It includes mailing lists, chat rooms, blogs, forums, Jabber networks, video, mail and telephone contacts.&lt;br /&gt;
====World Time Converter====&lt;br /&gt;
*http://www.timeanddate.com/worldclock/converter.html&lt;br /&gt;
&lt;br /&gt;
====Tiny URL====&lt;br /&gt;
*http://ietherpad.com/&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;ON-LINE VERSION&#039;&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;An expanded and enhanced listing of Items Included in the SugarCreationKit DVD ver 1.2.3 (see Above)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;NOTE: There are newer and additional items on this web page that are not in the SCK DVD.iso&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;big&amp;gt;&#039;&#039;Use to Download the elements you need and burn to your own DVD to save Downloading all of the above SCK DVD.iso&#039;&#039;&amp;lt;/big&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
: Look below to the [[#References|References section]] to see how to then convert your customized DVD to an .iso&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Introduction to &#039;&#039;&#039;[[Sugar on a Stick]]&#039;&#039;&#039;====&lt;br /&gt;
:::&#039;&#039;&#039;Read this first ^&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Cautions with using Live USB&#039;s.pdf&lt;br /&gt;
&lt;br /&gt;
*[[Sugar on a Stick/Installation/Variations#Cautions with using Live USB devices]]&lt;br /&gt;
&lt;br /&gt;
How to Make a live USB.pdf:&lt;br /&gt;
*(instructions on how to make a live USB in Windows, GNU/Linux, and Intel Mac&#039;s) [[Sugar on a Stick/Installation#with Microsoft Windows]]&lt;br /&gt;
*WINDOWS: [[Sugar on a Stick/Windows]]&lt;br /&gt;
&lt;br /&gt;
====[[File:SugaronastickMirabelle.png|240px]]  How to use Sugar on a Stick (SoaS)====&lt;br /&gt;
&lt;br /&gt;
# [[Downloads|Download]]&lt;br /&gt;
# [[Sugar_on_a_Stick/Installation|Install]]&lt;br /&gt;
# [[Sugar_on_a_Stick/Boot|Boot]]&lt;br /&gt;
# [[Sugar_on_a_Stick/Usage|Use]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Burn a SoaS.iso to a CD and Boot with the resulting CD&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====[[File:SugaronastickMirabelle.png|120px]][http://wiki.sugarlabs.org/go/Community/Distributions/Fedora-SoaS Tests of Nightly Composes]=====&lt;br /&gt;
::Click link to open ^&lt;br /&gt;
:http://wiki.sugarlabs.org/go/Community/Distributions/Fedora-SoaS&lt;br /&gt;
:http://alt.fedoraproject.org/pub/alt/nightly-composes/current.html&lt;br /&gt;
&lt;br /&gt;
=====[[File:XO_buddy.png|40px]][http://wiki.sugarlabs.org/go/Community/Distributions/Fedora-SoaS#SoaSv5-20110415-i6865 SoaS v5-20110415 Beta]=====&lt;br /&gt;
:http://wiki.sugarlabs.org/go/Community/Distributions/Fedora-SoaS#SoaSv5-20110415-i686  Note actually x86-64&lt;br /&gt;
;::&#039;&#039;&#039;Beta Version for testing only&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====[[File:XO_buddy.png|40px]][[Sugar_on_a_Stick/Mango_Lassi|SoaS v4 Mango Lassi]]=====&lt;br /&gt;
:click link ^ for details&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;(The current version of Sugar on a Stick)&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://alt.fedoraproject.org/pub/alt/spins/linux/releases/14/Spins/i686/Fedora-14-i686-Live-SoaS.iso download Mango Lassi]&#039;&#039;&#039; (32-bit build)&lt;br /&gt;
*&#039;&#039;&#039;[http://alt.fedoraproject.org/pub/alt/spins/linux/releases/14/Spins/x86_64/Fedora-14-x86_64-Live-SoaS.iso download Mango Lassi]&#039;&#039;&#039; (64-bit build)&lt;br /&gt;
: (Burn the .iso to a CD and Boot with the resulting CD)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Activities Compatible with Mango Lassi &amp;amp; Mirabelle  &lt;br /&gt;
:&#039;&#039;&#039;Editable Listing of Activity Compatibility&#039;&#039;&#039;  [[Features/Soas_V4/ASLOxo Activity Test Table]]  &#039;&#039;&#039;Please Use this wiki page to report your findings&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====[[File:XO_buddy.png|40px]][http://download.sugarlabs.org/soas/releases/soas-3-mirabelle.iso SoaS v3 Mirabelle]=====&lt;br /&gt;
:Click link ^ to download&lt;br /&gt;
&lt;br /&gt;
=====[[File:XO_buddy.png|40px]][http://download.sugarlabs.org/soas/releases/soas-2-blueberry.iso  SoaS v2 Bluberry]=====&lt;br /&gt;
::Click link ^ to download&lt;br /&gt;
&lt;br /&gt;
====Spins Archives====&lt;br /&gt;
*&#039;&#039;&#039;[http://download.sugarlabs.org/soas/releases/ Sugarlabs Archive to download Mirabelle and earlier SoaS versions]&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://alt.fedoraproject.org/pub/alt/spins/linux/releases/13/Spins/ Fedora 13 Spins Archive]&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://alt.fedoraproject.org/pub/alt/spins/linux/releases/14/Spins/ Fedora 14 Spins Archive]&#039;&#039;&#039;&lt;br /&gt;
: (Burn the .iso to a CD and Boot with the resulting CD)&lt;br /&gt;
*&#039;&#039;&#039;[[Talk:Sugar_on_a_Stick_release_process#Test_Matix|Testing of nightly spins]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Hardware Compatibility====&lt;br /&gt;
:EeePC: http://fedoraproject.org/wiki/EeePc&lt;br /&gt;
:[http://www.mydigitallife.info/2008/07/06/comprehensive-list-of-how-key-to-press-to-access-bios-for-various-oem-and-computer-systems/ key-to-press-to-access-bios-for-various-oem-and-computer-systems]&lt;br /&gt;
&lt;br /&gt;
:smolt profiles:http://www.smolts.org/&lt;br /&gt;
::http://smolts.org/smolt-wiki/Main_Page#Usage&lt;br /&gt;
&lt;br /&gt;
====[[Sugar_Creation_Kit/Sck/SoaS_installation_variations|SoaS Installation variations]]====&lt;br /&gt;
:Click Link ^&lt;br /&gt;
: A collection of install methods&lt;br /&gt;
&lt;br /&gt;
====[[:Category:Live USB]]====                &lt;br /&gt;
:click link ^&lt;br /&gt;
:A collection of links on how Live USB&#039;s are used in different distributions&lt;br /&gt;
=====Commercial Source of Live SoaS Sticks=====&lt;br /&gt;
*http://on-disk.com/product_info.php/cPath/28_310/products_id/908#!tab6&lt;br /&gt;
=====WiFi=====&lt;br /&gt;
:Wifi (Open FirmWare for WiFi networks): http://www.ing.unibs.it/~openfwwf/&lt;br /&gt;
::http://www.ing.unibs.it/openfwwf/&lt;br /&gt;
:http://www.h-node.com/wifi/view/en/2/BCM4311--rev-02-/1/1/Broadcom/undef/undef/undef/undef&lt;br /&gt;
:http://linuxwireless.org/en/users/Drivers/b43#Known_PCI_devices&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;[[Community/Distributions| Community Distributions]]&#039;&#039;&#039;====&lt;br /&gt;
: click this link^for complete listing&lt;br /&gt;
:&#039;&#039;&#039;Linux distributions where sugar is used:&#039;&#039;&#039;&lt;br /&gt;
:[[Image:Fedora-small.jpg|link=Community/Distributions/Fedora]][[Community/Distributions/Fedora|Fedora]] F13 SoaS, F14 SoaS, f15-gnome3-shell and sugar0.92.0 How to install Sugar packages &lt;br /&gt;
:[[File:Trisquel_icon.png|link=Community/Distributions/Trisquel]][[Community/Distributions/Trisquel|Trisquel]] Tris 4.0 (Ubuntu 10.04LTS); Tris 4.5 (Ubuntu 10.10); Sugar sweets 0.88.1 or 0.90.1&lt;br /&gt;
:[[Image:Mandriva-small.png|link=Community/Distributions/Mandriva]][[Community/Distributions/Mandriva|Mandriva]] 2010.2 Mandriva Sugar 0.88.0&lt;br /&gt;
:[[Image:Debian-small.jpg|link=Community/Distributions/Debian]][[Community/Distributions/Debian|Debian]] Debian 6 Sugar 0.88.1&lt;br /&gt;
:[[File:LMD-small.png|link=Community/Distributions/Linux_Mint_Debian]][[Community/Distributions/Linux_Mint_Debian|Linux Mint Debian]] Debian 6  Sugar 0.88.1&lt;br /&gt;
:[[Image:Caixa_M%C3%A1gica-small.jpg|link=Community/Distributions/Magalhães]][[Community/Distributions/Magalhães|Caixa Mágica]] based on Mandriva 2010.1 repositories Sugar 0.88.0&lt;br /&gt;
:[[Image:Ubuntu-small.jpg|link=Community/Distributions/Ubuntu]][[Community/Distributions/Ubuntu|Ubuntu]] Sugar sweets 0.88.1 or 0.90.1&lt;br /&gt;
:[[Image:Suse-small.jpg|link=Community/Distributions/OpenSUSE]][[Community/Distributions/OpenSUSE| openSUSE]]&lt;br /&gt;
:[[Image:Tuquito.png|link=Community/Distributions/tuquito]][http://wiki.sugarlabs.org/go/Community/Distributions/tuquito tuquito] NEW Community Distribution based on Ubuntu 10.10&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;[http://download.sugarlabs.org/soas/releases/ Sugar Labs Archive to download Mirabelle and earlier SoaS versions]&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;[http://alt.fedoraproject.org/pub/alt/spins/linux/releases/13/Spins/ Fedora Spins Archive]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=====[[File:Gnome_icon.png]][http://wiki.sugarlabs.org/go/Community/Distributions/Fedora#Fedora_15_gnome3_with_sugar_0.92.0 Fedora 15 gnome3 with sugar 0.92.0]=====&lt;br /&gt;
:click this ^ link&lt;br /&gt;
{{Admon/note|Note:|This is an Beta Version-for testing sugar and sugar-emulator in the next version of Fedora 15. It can be Updated to gnome3-shell 3.0.1 }}&lt;br /&gt;
&lt;br /&gt;
====[http://download.sugarlabs.org/ Index of Sugar Labs Archive]====&lt;br /&gt;
*click above link ^&lt;br /&gt;
&lt;br /&gt;
====[[Sck/ASLOxo|ASLOxo-5.iso]]====&lt;br /&gt;
*click above link ^&lt;br /&gt;
*(275.xo files and worldmap.pdf files)&lt;br /&gt;
:&#039;&#039;&#039;New: Updated activities through 02/08/2011&#039;&#039;&#039;&lt;br /&gt;
*[http://download.sugarlabs.org/images/ASLOxo-5.iso ASLOxo-5.iso] 1.3 GB (DVD)&lt;br /&gt;
*[http://download.sugarlabs.org/images/Contents_of_ASLOxo-5-iso.txt View: Contents_of_ASLOxo-5-iso.txt] 8.5K&lt;br /&gt;
&lt;br /&gt;
* These can be copied to a 2-GB USB device and drag-­dropped into the Sugar Journal to install them.&lt;br /&gt;
&lt;br /&gt;
====[[Sck/activities|Activities]]====&lt;br /&gt;
*click above link ^&lt;br /&gt;
*&#039;&#039;&#039;listing:  [[Activities]]&#039;&#039;&#039; Descriptions and Developer Pages&lt;br /&gt;
*  OLPC listings: &#039;&#039;&#039;[http://wiki.laptop.org/index.php?title=Category:Activities Activities]&#039;&#039;&#039;&lt;br /&gt;
*  OLPC AU: [http://wiki.laptop.org/go/Activities/OLPCAU/10.1.3 Activities_OLPCAU_10.1.3]&lt;br /&gt;
* &#039;&#039;&#039;[http://wiki.laptop.org/go/Recursos_en_espanol Recursos_en_espanol]  &#039;&#039;&#039;Los siguientes recursos han sido creados por personal de distintos deployments de America Latina y otros colaboradores.&lt;br /&gt;
======Etoys-116 Soasv5 RC3 Error Fix======&lt;br /&gt;
 presence-service is obsolete, but etoys still uses it and nothing else. No idea why it no longer runs.&lt;br /&gt;
 Because PS does not find the buddy icon file. If I do&lt;br /&gt;
     &#039;&#039;&#039;touch ~/.sugar/default/buddy-icon.jpg&#039;&#039;&#039;&lt;br /&gt;
 then Etoys starts fine. - Bert -&lt;br /&gt;
&lt;br /&gt;
=====logo=====&lt;br /&gt;
*http://logoworks.wikispaces.com/&lt;br /&gt;
=====surf browser=====&lt;br /&gt;
: alternate to sugar-browse&lt;br /&gt;
; Included in latest f15 sugar 0.92.1 as the main web browser&lt;br /&gt;
:: Works in situations where sugar-browse will not start&lt;br /&gt;
* Download: http://people.sugarlabs.org/Tgillard/Surf-115.xo&lt;br /&gt;
* RPM: http://koji.fedoraproject.org/koji/getfile?taskID=3008630&amp;amp;name=sugar-surf-115-1.fc16.noarch.rpm&lt;br /&gt;
* git: http://git.sugarlabs.org/surf&lt;br /&gt;
&lt;br /&gt;
=====Turtle art 107-1 rpm=====&lt;br /&gt;
*http://kojipkgs.fedoraproject.org/packages/sugar-turtleart/107/1.fc15/noarch/sugar-turtleart-107-1.fc15.noarch.rpm&lt;br /&gt;
: for f15&lt;br /&gt;
; Included in latest f15 sugar 0.92.1&lt;br /&gt;
*http://koji.fedoraproject.org/koji/buildinfo?buildID=239454&lt;br /&gt;
&lt;br /&gt;
====DVD covers; artwork &amp;amp; screenshots====&lt;br /&gt;
* sugarlabs_SoaS-Creation-Kit_avery_cd_label_2up.pdf http://people.sugarlabs.org/Tgillard/sugarlabs_SoaS-Creation-Kit_avery_cd_label_2up_Mirabelle.pdf&lt;br /&gt;
* sugarlabs_Sugar-demo_avery_cd_label_2up.pdf http://people.sugarlabs.org/Tgillard/sugarlabs_Sugar-demo_avery_cd_label_2up_Mirabelle.pdf&lt;br /&gt;
* Flyer_englisch.pdf *http://people.sugarlabs.org/Tgillard/Flyer_englisch.pdf (Poster-Sugar Learning Program; 2-sided with text from past Show)&lt;br /&gt;
* Booth_Banners  http://wiki.sugarlabs.org/go/Marketing_Team/Booth_Banners&lt;br /&gt;
* LinuxTag http://www.flickr.com/photos/39656470@N02/sets/72157620524327203/ SeanDaly&lt;br /&gt;
* Screen Shots http://wiki.sugarlabs.org/go/Marketing_Team/Screen_Shots&lt;br /&gt;
* http://wiki.sugarlabs.org/go/Marketing_Team/T-Shirt  nice collection of images&lt;br /&gt;
* Fedora 15 Gnome3-shell with sugar-emulator: http://wiki.sugarlabs.org/go/Community/Distributions/Fedora#GnomeShell&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[[File:Sugarlabs_mainpage_07.png|link=http://en.flossmanuals.net/]]&#039;&#039;&#039;[http://en.flossmanuals.net/ Floss Manuals]&#039;&#039;&#039;&amp;lt;/span&amp;gt;====&lt;br /&gt;
:;Click this link ^&lt;br /&gt;
(Important Manuals on how to use Sugar Applications and Features)&lt;br /&gt;
:&#039;&#039;&#039;READ THESE FIRST!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;[http://people.sugarlabs.org/Tgillard/floss_manuals/ Sugarlabs Download Page]&#039;&#039;&#039;&lt;br /&gt;
::(Local ARCHIVE of the.pdf files shown below:)&lt;br /&gt;
&lt;br /&gt;
:* Source Links:&lt;br /&gt;
&lt;br /&gt;
:: Introduction to Sugar http://en.flossmanuals.net/sugar&lt;br /&gt;
:::&#039;&#039;&#039;[http://www.archive.org/details/MakeYourOwnSugarActivities MakeYourOwnSugarActivities] Internet Archive&#039;&#039;&#039; Publishing Quality&lt;br /&gt;
:::: In PDF, EPUB, Kindle, Daisy, Full Text. DjVu formats&lt;br /&gt;
:::[http://people.sugarlabs.org/Tgillard/floss_manuals/ActivitiesGuideSugares-es-2011.01.21-18.28.05.pdf MakeYourOwnSugarActivities-es] with corrected index&lt;br /&gt;
:::What is Sugar http://people.sugarlabs.org/Tgillard/floss_manuals/What_is_Sugar_28Oct08.pdf&lt;br /&gt;
:::Browse http://people.sugarlabs.org/Tgillard/floss_manuals/Browse_06Sep08.pdf&lt;br /&gt;
:::Chat  http://people.sugarlabs.org/Tgillard/floss_manuals/Chat_09Sep08.pdf&lt;br /&gt;
:::Collaboration  http://people.sugarlabs.org/Tgillard/floss_manuals/Collaboration_31Jan10.pdf&lt;br /&gt;
:::SugarCollaboration http://en.flossmanuals.net/ActivitiesGuideSugar/SugarCollaboration&lt;br /&gt;
:::FunWithTheJournal  http://people.sugarlabs.org/Tgillard/floss_manuals/Fun_with_the_journal_09Nov10.pdf&lt;br /&gt;
:::Linux Command Line http://people.sugarlabs.org/Tgillard/floss_manuals/Linux-command-line_16Apr09.pdf&lt;br /&gt;
:::ActivitiesGuideSugar-English   http://people.sugarlabs.org/Tgillard/floss_manuals/Activitys_Guide-sugar_en_09Nov10.pdf&lt;br /&gt;
:::Record http://people.sugarlabs.org/Tgillard/floss_manuals/Record_06Sep08.pdf&lt;br /&gt;
:::The Terminal  http://people.sugarlabs.org/Tgillard/floss_manuals/Terminal_06Sep08.pdf&lt;br /&gt;
:::Turtle Art  http://people.sugarlabs.org/Tgillard/floss_manuals/TurtleArt_06Sep08.pdf&lt;br /&gt;
:::Write  http://people.sugarlabs.org/Tgillard/floss_manuals/Write_27Sep08.pdf&lt;br /&gt;
:::Reading_and_sugar: http://people.sugarlabs.org/Tgillard/floss_manuals/Reading_and_sugar_28Sep10.pdf&lt;br /&gt;
:::Text to Speech: http://people.sugarlabs.org/Tgillard/floss_manuals/Text_and_Speak_09Nov10.pdf&lt;br /&gt;
&lt;br /&gt;
====Booki====&lt;br /&gt;
*[http://book.treehouse.su/ Sugarlabs Booki]&lt;br /&gt;
:click this link ^&lt;br /&gt;
; (This is a site under construction)&lt;br /&gt;
 Edward Cherlin wrote:&lt;br /&gt;
 [IAEP] Fwd: New booki for replacing textbooks with OER 04/01/2011&lt;br /&gt;
 &lt;br /&gt;
 Please take a look at&lt;br /&gt;
 &lt;br /&gt;
  http://booki.flossmanuals.net/&lt;br /&gt;
 &lt;br /&gt;
  a site for collaborative authoring and publishing of manuals for Open&lt;br /&gt;
  Source software. Sugar Labs has set up another trial instance of the&lt;br /&gt;
  same booki software for OER development. I am arranging for some&lt;br /&gt;
  further administrative changes so that we can begin to use it, and&lt;br /&gt;
  will then invite various interested persons and groups to try it out&lt;br /&gt;
  and to discuss what we might be able to do by combining this with&lt;br /&gt;
  Sugar and other education software.&lt;br /&gt;
 &lt;br /&gt;
:[http://www.crowdrise.com/Replacetextbooks/ Replacetextbooks]&lt;br /&gt;
:[http://www.booki.cc/booki-user-guide/ Booki User Guide]&lt;br /&gt;
:[http://support.booki.cc/ Support]&lt;br /&gt;
:[http://blog.booki.cc/ Blog]&lt;br /&gt;
:[http://book.treehouse.su/meta/_v/1.0/importing-a-book/ Booki importing-a-book]&lt;br /&gt;
:http://booki.flossmanuals.net/ FLOSS Manuals WRITE&lt;br /&gt;
::http://booki.flossmanuals.net/xo  Depreciated&lt;br /&gt;
====[http://mapmeld.appspot.com/khan_categories.html Khan Academy videos in OGV format]====&lt;br /&gt;
:click this link ^&lt;br /&gt;
:Re: [IAEP] Khan academy content   04/05/2011&lt;br /&gt;
 You can download around 1000 of the Khan Academy videos in OGV format&lt;br /&gt;
 (playable on XO laptops) from Archive.org   Here&#039;s an English/Spanish&lt;br /&gt;
 index of relevant categories&lt;br /&gt;
 If you&#039;re skeptical or haven&#039;t seen his videos, his talk sparked a great&lt;br /&gt;
 discussion about math education on Hacker News:&lt;br /&gt;
 http://news.ycombinator.com/item?id=2307532&lt;br /&gt;
 &lt;br /&gt;
 For more recent videos, including YouTube, there&#039;s this media guide:&lt;br /&gt;
 http://wiki.laptop.org/go/MediaGuide&lt;br /&gt;
 &lt;br /&gt;
 Regards,&lt;br /&gt;
 Nick Doiron&lt;br /&gt;
*link:http://www.khanacademy.org/&lt;br /&gt;
&lt;br /&gt;
=====Flash Player=====&lt;br /&gt;
: needed for firefox viewing of Khan academy lectures&lt;br /&gt;
*http://plugindoc.mozdev.org/linux.html#Flash&lt;br /&gt;
&lt;br /&gt;
====References====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;How to make your own custom Sugar-Creation_Kit.iso file&#039;&#039;&#039; (How this DVD was converted to an .iso file)&lt;br /&gt;
*# Collect, annotate and sort the files you want in a folder on your Desktop.&lt;br /&gt;
*# Burn the contents of this folder to a CD or DVD.&lt;br /&gt;
*# Use the following command in Terminal as the root user:&lt;br /&gt;
*#: &amp;lt;big&amp;gt;&amp;lt;code&amp;gt;dd if=/dev/sr0 of=Sugar-Creation-Kit.iso&amp;lt;/code&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
*: Sample output:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dd if=/dev/sr0 of=Sugar-Creation-Kit.iso&lt;br /&gt;
 5555584+0 records in&lt;br /&gt;
 5555584+0 records out&lt;br /&gt;
 2844459008 bytes (2.8 GB) copied, 232.86 s, 12.2 MB/s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
*the resulting .iso file can be sent over the internet or used to make copies by burning to a DVD&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;How To Sugarize a Program&#039;&#039;&#039;&lt;br /&gt;
:Instructions on how to make a program appear in the (F3) Home view of Sugar as an icon&lt;br /&gt;
:: http://people.sugarlabs.org/Tgillard/sugarize/wiki-sugarize.txt&lt;br /&gt;
:: [[Running Linux Applications Under Sugar]]&lt;br /&gt;
====&#039;&#039;&#039;[[The Undiscoverable]]&#039;&#039;&#039;====&lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
: (The Undiscoverable Features of Sugar)&lt;br /&gt;
: Features and tips not easily discovered about using Sugar&lt;br /&gt;
=====HTMLDOC=====&lt;br /&gt;
*http://www.htmldoc.org/documentation.php/Introduction.html&lt;br /&gt;
 HTMLDOC software, version 1.8.27. HTMLDOC converts Hyper-Text Markup Language (&amp;quot;HTML&amp;quot;) input files&lt;br /&gt;
 into indexed HTML, Adobe® PostScript®, or Adobe Portable Document Format (&amp;quot;PDF&amp;quot;) files.&lt;br /&gt;
&lt;br /&gt;
====E-books====&lt;br /&gt;
&lt;br /&gt;
* [[Education Team/Creating textbooks]]&lt;br /&gt;
*Reading And Leading With One Laptop Per Child http://en.flossmanuals.net/ReadingandSugar/Introduction&lt;br /&gt;
&lt;br /&gt;
====Graphic installers====&lt;br /&gt;
=====[http://wiki.sugarlabs.org/go/Sugar_Creation_Kit/Sck/Liveusb-creator Liveusb Creator]=====&lt;br /&gt;
:Click link above ^ for details&lt;br /&gt;
::Fedora and Windows (BEST METHOD TO USE)&lt;br /&gt;
&lt;br /&gt;
* how to create and use liveusb-creator  [[fedora:FedoraLiveCD/USBHowTo]] [[fedora:How to create and use Live USB#Graphical Method - Windows or Fedora]]&lt;br /&gt;
* Liveusb-­creator  https://fedorahosted.org/liveusb-creator/&lt;br /&gt;
* F14 version for windows released: http://lewk.org/blog/liveusb-creator-3.9.3.html 01/06/2011&lt;br /&gt;
&lt;br /&gt;
=====ZyX-LiveInstaller=====&lt;br /&gt;
* [[Sugar on a Stick/ZyX-LiveInstaller]]&lt;br /&gt;
: http://en.wikipedia.org/wiki/Loopback_disk_device&lt;br /&gt;
&lt;br /&gt;
=====UNetbootin=====&lt;br /&gt;
* [http://unetbootin.sourceforge.net/unetbootin-windows-latest.exe unetbootin­windows­471.exe for windows]&lt;br /&gt;
* [http://unetbootin.sourceforge.net/unetbootin-linux-latest unetbootin­linux­471]&lt;br /&gt;
* [http://unetbootin.sourceforge.net/ UNetbootin]&lt;br /&gt;
* (Advanced)  [http://sourceforge.net/apps/trac/unetbootin/wiki/commands UNetbootin ­Command line]&lt;br /&gt;
* [[Community/Distributions/Linux_Mint_Debian#How_to_Make_a_2GB_Installer_USB|How to Make a 2GB Installer USB with UNetbootin]]&lt;br /&gt;
&lt;br /&gt;
=====pendrivelinux=====&lt;br /&gt;
*[http://www.pendrivelinux.com/category/usb-installs-from-linux/ usb-installs-from-linux] How to Do it Information&lt;br /&gt;
*[http://www.pendrivelinux.com/universal-usb-installer-easy-as-1-2-3/ universal-usb-installer-easy-as-1-2-3] Windows&lt;br /&gt;
*[http://www.pendrivelinux.com/boot-multiple-iso-from-usb-via-grub2-using-linux/ boot-multiple-iso-from-usb-via-grub2-using-linux] linux (Advanced)&lt;br /&gt;
*[http://www.pendrivelinux.com/boot-a-usb-flash-drive-in-virtualbox/#more-3606 boot-a-usb-flash-drive-in-virtualbox] VirtualBox&lt;br /&gt;
=====openSUSE Live USB stick=====&lt;br /&gt;
*[http://en.opensuse.org/Live_USB_stick openSUSE Live USB stick]&lt;br /&gt;
*[http://software.opensuse.org/113/en Downloads]&lt;br /&gt;
====[http://wiki.sugarlabs.org/go/Sugar_Creation_Kit/Sck/Expert_install_methods Expert install methods]==== &lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
* [[Talk:Sugar on a Stick/Blueberry#liveinst command to install to Hard-Disk.2FUSB from Soas CD|How to install to a 4GB USB using liveinst (ANACONDA) from SoaS]]&lt;br /&gt;
&lt;br /&gt;
* Use livecd­-iso-to-disk script to write a live USB [[Sugar on a Stick/Linux]], [[Fedora:How to create and use Live USB#Graphical Method - Windows or Fedora|Fedora page]]&lt;br /&gt;
*:[[fedora:Livecd-iso-to-disk.pod|Technical Details]]&lt;br /&gt;
&lt;br /&gt;
* zyx­liveinstaller Instructions [[Sugar on a Stick/ZyX-LiveInstaller]]&lt;br /&gt;
*  Download: zyx­liveinstaller­0.2.4-­1.noarch.rpm http://people.sugarlabs.org/Tgillard/zyx-liveinstaller-0.2.4-1.noarch.rpm&lt;br /&gt;
=====&amp;lt;big&amp;gt;[[Sugar_Creation_Kit/sck/dd_installs|Use &amp;quot;dd&amp;quot; command]]&amp;lt;/big&amp;gt; =====&lt;br /&gt;
:click this link ^ for more details and examples. For ADVANCED USERS ONLY.&lt;br /&gt;
: &#039;&#039;&#039;to make an install USB from a liveCD .iso file&#039;&#039;&#039;&lt;br /&gt;
*Also see: [[Sugar_on_a_Stick/Linux/openSUSE|openSUSE dd to USB with persistence]]&lt;br /&gt;
*Great for netbooks&lt;br /&gt;
:Use (live).iso and terminal to make bootable USB&lt;br /&gt;
::Use to install to HD or USB without needing a DVD/CD ROM&lt;br /&gt;
&lt;br /&gt;
=====[http://wiki.sugarlabs.org/go/Sugar_Creation_Kit/sck/Building_a_bootable_Mac_USB Building a bootable Mac USB]=====&lt;br /&gt;
:Click above Link ^&lt;br /&gt;
:: (tested on a MacBook Air)&lt;br /&gt;
&lt;br /&gt;
=====Boot Helper CD&#039;s=====&lt;br /&gt;
*MAC SoaS-3 Mirabelle Boot DISK&lt;br /&gt;
::[http://people.sugarlabs.org/Tgillard/soas-3-boot-test.iso soas-3-boot-test.iso] (Burn this to a CD and boot with it)&lt;br /&gt;
::[http://people.sugarlabs.org/Tgillard/soas-3-boot-test.txt Read Me First &amp;amp; Credits to Programmer] &lt;br /&gt;
*MAC SoaS-4 Mango Lassi Boot DISK&lt;br /&gt;
::[http://www.wronkiewicz.net/soas-4-boot-test.iso soas-4-boot-test] (Burn this to a CD and boot with it)&lt;br /&gt;
*rEFIt&lt;br /&gt;
::[http://refit.sourceforge.net/doc/ rEFIt]&lt;br /&gt;
::[http://refit.sourceforge.net/doc/c1s5_burning.html burn a bootable rEFIt CD on Mac OS X] Used to Boot live USB&#039;s in a Mac&lt;br /&gt;
 rEFIt is a boot menu and maintenance toolkit for EFI-based machines like the Intel Macs.&lt;br /&gt;
 You can use it to boot multiple operating systems easily, including triple-boot setups with Boot Camp.&lt;br /&gt;
 It also provides an easy way to enter and explore the EFI pre-boot environment.&lt;br /&gt;
&lt;br /&gt;
====Backup and Restore====&lt;br /&gt;
* Backup  (Activity)  http://activities.sugarlabs.org/en-US/sugar/addon/4326&lt;br /&gt;
* Restore  (Activity) http://activities.sugarlabs.org/en-US/sugar/addon/4327&lt;br /&gt;
&lt;br /&gt;
* Mirabelle backup (deja-­dup)  [[Sugar on a Stick/deja-dup]]&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;[[QEMU|QEMU Virtualization]]&#039;&#039;&#039;====&lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
&lt;br /&gt;
:In Gnome terminal:&lt;br /&gt;
 su&lt;br /&gt;
 yum install @virtualization&lt;br /&gt;
&lt;br /&gt;
::Start (Graphical): Applications/System Tools/Virtual Machine Manager&lt;br /&gt;
&lt;br /&gt;
*installs soas.iso files to VM HD (with liveinst command in terminal of running Virtual Machine)&lt;br /&gt;
&lt;br /&gt;
====BoxGrinder====&lt;br /&gt;
*http://boxgrinder.org&lt;br /&gt;
*http://boxgrinder.org/tutorials/&lt;br /&gt;
:BoxGrinder creates appliances (also called images) from simple plain text Appliance Definition files.&lt;br /&gt;
*http://boxgrinder.org/tutorials/boxgrinder-build-meta-appliance/&lt;br /&gt;
*http://boxgrinder.org/download/boxgrinder-build-meta-appliance/&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;[[VMware]] Player Virtualization&#039;&#039;&#039;====&lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
[https://www.vmware.com/tryvmware/?p=player&amp;amp;lp=default Download VMware Player (free)]&lt;br /&gt;
&lt;br /&gt;
====VMware Player Appliances====&lt;br /&gt;
* VMware Player appliance of SoaS-v3-Mirabelle&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Soas-v3-Mirabelle.zip Download]&lt;br /&gt;
::This appliance is ready to run &amp;quot;firstboot&amp;quot; (agree/user name/password/tz/etc) &lt;br /&gt;
::&#039;&#039;&#039;sugarroot&#039;&#039;&#039; is the root password.&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-3 (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel3.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Trisquel-4+sugar (NEW) 01/05/2011&lt;br /&gt;
:Compressed in .zip file &lt;br /&gt;
:[http://download.sugarlabs.org/images/vmplayer/Trisquel-4-sugar-VMPlayer.zip download]&lt;br /&gt;
::User=sugar&lt;br /&gt;
::Password=sugaruser&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance Sugar on a Stick v2 (Blueberry)&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.txt Read this first.]&lt;br /&gt;
:[http://people.sugarlabs.org/Tgillard/Blueberry-vmx.tar.gz download]&lt;br /&gt;
&lt;br /&gt;
* VMware Player appliance of openSUSE-Sugar&lt;br /&gt;
:[[VMware#openSUSE |Read this first.]]&lt;br /&gt;
:[http://sourceforge.net/projects/opensuse-edu/files/Sugar/openSUSE-Sugar-vmware-vmx.tar.bz2/download download]&lt;br /&gt;
:[[Talk:VMware#change_networking|networking help]]&lt;br /&gt;
:[http://old-en.opensuse.org/How_to_use_downloaded_SUSE_Studio_appliances how to use]&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;[[VirtualBox|VirtualBox Virtualization]]&#039;&#039;&#039;====&lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
With [[wikipedia:VirtualBox|VirtualBox&amp;lt;sup&amp;gt;®&amp;lt;/sup&amp;gt;]] one can run Sugar in a window on Microsoft Windows, Intel-based  Apple Macintosh, or Linux host computers from a virtual machine (VM) window. [http://www.oracle.com/technetwork/server-storage/virtualbox/overview/index.html VirtualBox overview]&lt;br /&gt;
* [[VirtualBox]]&lt;br /&gt;
* A good solution for Macintosh computers&lt;br /&gt;
&lt;br /&gt;
*[http://www.virtualbox.org/wiki/Downloads VirtualBox downloads] Windows/Linux/Intel Macs&lt;br /&gt;
*[http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html Oracle VirtualBox downloads] (alternate link)&lt;br /&gt;
*[http://www.virtualbox.org/manual/ch02.html#id352318 Installing on Linux hosts] Read this if VirtualBox does not install.&lt;br /&gt;
*[http://forums.virtualbox.org/viewforum.php?f=8 VirtualBox on Mac OS X Hosts]&lt;br /&gt;
=====[http://people.sugarlabs.org/Tgillard/Trisquel41_sugar_installer.iso &#039;&#039;&#039;Trisquel41_sugar_installer.iso&#039;&#039;&#039;]=====&lt;br /&gt;
*click above link &#039;&#039;&#039;^&#039;&#039;&#039; to download (1.1GB) &lt;br /&gt;
*&#039;&#039;&#039;This DVD.iso is a great way to &amp;quot;SneakerNet&amp;quot; distribute this VM Appliance&#039;&#039;&#039;&lt;br /&gt;
:Revised 03/02/2011 to remove sugar identity&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
*Contents of DVD:&lt;br /&gt;
: Instructions and .vmdk/.ovf files to import&lt;br /&gt;
 32bit-VirtualBox Installers (OSE) (Directory with install files for VirtualBox 4.0.4)&lt;br /&gt;
 (Does not include Free for Personal Use licensed extension pack) - includes instructions on how to download for personal use.&lt;br /&gt;
 ReadMeFirst_Install_Instructions.pdf  (Instructions-how to install VirtualBox and import appliance)&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18.ovf&lt;br /&gt;
 trisquel-sugar-4.1-i686-feb18-disk1.vmdk&lt;br /&gt;
 UserManual.pdf (VirtualBox 4.0.4 User Manual-269 pages)&lt;br /&gt;
&lt;br /&gt;
* Cleared of Sugar Learner identity. Starts on color selection screen (Click the &amp;lt;===(back) button to change the Learner name.)&lt;br /&gt;
&lt;br /&gt;
{{Admon/note|&lt;br /&gt;
* &#039;&#039;&#039;When making a new VM&#039;&#039;&#039;, to clear the Sugar Journal of old entries and to avoid identity conflicts among copies of the VM, enter the command {{Code|rm&amp;amp;nbsp;~&amp;amp;nbsp;rf&amp;amp;nbsp;/.sugar}} in the Terminal activity. Then shutdown the VM. This will clear all Learner information on the VM and let you start with a fresh install. Skipping this will result in collisions in the Neighborhood view of the Jabber network between separate copies of the appliance. Verify the presence of the &#039;&#039;&#039;.sugar&#039;&#039;&#039; directory by entering {{Code|ls&amp;amp;nbsp;-a}} in Terminal.&lt;br /&gt;
* &#039;&#039;&#039;When cloning a customized VM&#039;&#039;&#039;, in order to keep the Journal and installed .xo Activities, use {{Code|rm&amp;amp;nbsp;~/.sugar/default/owner.key*}} in the Sugar Terminal, and then shutdown the VM. This leaves the Journal entries and removes only the previous Learner&#039;s identity key files.}}&lt;br /&gt;
&lt;br /&gt;
[[File:VirtualBox.png|75px|link=Emulator image files]]&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;[[Emulator_image_files|All Prebuilt VirtualBox Appliances]]&#039;&#039;&#039;====&lt;br /&gt;
: click this link ^ to see a complete list of available VirtualBox Appliances&lt;br /&gt;
::Try the appliances listed below first.&lt;br /&gt;
::they are listed with the Recommended version first and older ones below.&lt;br /&gt;
&lt;br /&gt;
====[[File:Trisquel_icon.png]][http://wiki.sugarlabs.org/go/Emulator_image_files/Trisquel#Trisquel-4.1-sugar Trisquel-4.1-sugar]====&lt;br /&gt;
&lt;br /&gt;
:(click this ^ link for details)&lt;br /&gt;
:&#039;&#039;&#039;RECOMMENDED&#039;&#039;&#039;&lt;br /&gt;
* Sugar Desktop ONLY&lt;br /&gt;
: Ubuntu 10.04 LTS with Sugar sweets 0.88.1&lt;br /&gt;
&lt;br /&gt;
*:[[Community/Distributions/Trisquel]]&lt;br /&gt;
&lt;br /&gt;
* download and import 2 files:&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned-disk1.vmdk&lt;br /&gt;
*# http://people.sugarlabs.org/Tgillard/trisquel-sugar-4.1-i686-Cloned.ovf&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Cleared of sugar identity; Starts on Color Selection Screen ( &amp;lt;===(back) to change/ customize name)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]]  Sugar on a Stick v3 Mirabelle ====&lt;br /&gt;
&lt;br /&gt;
::firstboot has not yet run; so a new user name and password will be set for the gdm login on startup for the first time&lt;br /&gt;
:How Built:&lt;br /&gt;
: &#039;&#039;&#039;root=sugarroot&#039;&#039;&#039;&lt;br /&gt;
: 8-GB VirtualBox hard disc &lt;br /&gt;
:English and English keyboard &lt;br /&gt;
:USA-Los Angeles (Pacific timezone)&lt;br /&gt;
:&#039;&#039;&#039;download and import 2 files:&#039;&#039;&#039;&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.vmdk 533M&lt;br /&gt;
 http://download.sugarlabs.org/images/VirtualBox/Fedora-13-i686-Live-SoaS-sugaruser.ovf   12K&lt;br /&gt;
&lt;br /&gt;
*Note1:Use the latest version of Oracle VM VirtualBox (3.2_10.8-64453 or later). Some appliances have multiple hard disc controllers and the earlier Sun VirtualBox 3.1 version does not support them.&lt;br /&gt;
*Note2: All appliances were built on a MacBook Air with Oracle VM VirtualBox (3.2.10-r66523) then tested on a Ubuntu installation on an Acer Aspire One Netbook imported into VirtualBox (3.2.10 r66523)&lt;br /&gt;
*Note3:Set ControlPanel/Frame &amp;quot;Edge&amp;quot; slider to far left for easier access to sugar-frame features&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====[[Image:Fedora-small.jpg]] Sugar on a Stick v2 Blueberry ====&lt;br /&gt;
&lt;br /&gt;
:READ FIRST: http://people.sugarlabs.org/Tgillard/soas-2-blueberry_ovf_README_FIRST.txt&lt;br /&gt;
:: Download these three files:&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/soas-2-blueberry.vmdk&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/soas-2-blueberry.ovf&lt;br /&gt;
 http://people.sugarlabs.org/Tgillard/soas-2-blueberry.mf&lt;br /&gt;
&lt;br /&gt;
====Sugar Clone====&lt;br /&gt;
: &#039;&#039;&#039;customize or duplicate Live USB installations&#039;&#039;&#039;&lt;br /&gt;
: (script files for making a customized Live USB installation self­-replicating)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Sugar Clone­ Wiki Page&#039;&#039;&#039; [[Sugar on a Stick/Sugar Clone]]&lt;br /&gt;
&lt;br /&gt;
:Update:  http://www.mail-archive.com/soas@lists.sugarlabs.org/msg02044.html&lt;br /&gt;
:::Rebuild/Refresh a custom SoaS iso from a running stick&lt;br /&gt;
&lt;br /&gt;
=====Possible Use Cases=====&lt;br /&gt;
(from Wiki Page)&lt;br /&gt;
:&#039;&#039;&#039;Curriculum packaging&#039;&#039;&#039;&lt;br /&gt;
   1. A teacher wants to prepare a SoaS image with a custom set of installed Activity bundles or a Journal of Activity instances for an upcoming class term.&lt;br /&gt;
   2. The teacher modifies their current working image by adding or deleting Activity bundles from their Home view and adding or removing Journal entries with specific content&lt;br /&gt;
    (such as a Physics model template or Etoys project), even saving distributable ebooks, or bookmarks in Browse Activity instances that are named for specific sets of local web destinations&lt;br /&gt;
    (a class portal perhaps for deployments lacking Internet connectivity).&lt;br /&gt;
   3. The teacher scrubs out any personal passwords or other history that should not be shared in the new copies.&lt;br /&gt;
   4. A fresh or recycled USB stick is inserted into the computer running the customized SoaS image and the SugarClone script is executed. &lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Full image backup or sharing&#039;&#039;&#039;&lt;br /&gt;
   1. A Learner has modified their environment, perhaps adding Activity bundles and prepared specific instances such as a Activities/Physics simulation.&lt;br /&gt;
   2. Their modifications include changes to their operating system installed through yum or RPM to obtain some new core functionality.&lt;br /&gt;
   3. The Learner wants to archive or share this image with friends or for a backup.&lt;br /&gt;
   4. Personal or private information is scrubbed from the Journal or Browse history and other potential stores.&lt;br /&gt;
   5. The User creates one or more Sugar Clones. &lt;br /&gt;
&lt;br /&gt;
This method of backup has the advantage that it copies Learner changes to the core operating system as well as the Journal. A LiveOS image using a separate persistent home folder could be partially cloned with either the operating system overlay or home folder without the other should that be desired.&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;&#039;[[Build Your Own Remix with Fedora]]&#039;&#039;&#039; (Advanced) ==&lt;br /&gt;
:click this link ^ for more details and examples&lt;br /&gt;
:Make your own Custom CD/DVD.iso with a customized kickstart file&lt;br /&gt;
&lt;br /&gt;
*Links to Trisquel, Debian and Mandriva on how to remix Live CD&#039;s&lt;br /&gt;
:http://trisquel.info/en/wiki/customizing-trisquel-iso&lt;br /&gt;
:http://wiki.debian.org/DebianCustomCD&lt;br /&gt;
:http://wiki.mandriva.com/en/Draklive&lt;br /&gt;
&lt;br /&gt;
==XO-1 &amp;amp; XO-1.5==&lt;br /&gt;
:http://wiki.laptop.org/go/OS_images&lt;br /&gt;
:http://wiki.sugarlabs.org/go/Dextrose&lt;br /&gt;
:http://build.laptop.org/11.2.0/os9/xo-1.5/&lt;br /&gt;
==XO-1.75==&lt;br /&gt;
*ARM&lt;br /&gt;
:http://wiki.laptop.org/go/XO-1.75&lt;br /&gt;
&lt;br /&gt;
==Fedora Sugar Bugs==&lt;br /&gt;
*[[Talk:Sugar_Creation_Kit|Must increase F15 RC1 netinstall Memory requirements]]&lt;br /&gt;
*https://bugzilla.redhat.com/buglist.cgi?component=sugar&amp;amp;product=Fedora&lt;br /&gt;
===[http://live.gnome.org/GnomeKeyring/RunningDaemon GnomeKeyring]===&lt;br /&gt;
:Login pops up 11 times when starting sugar-emulator:&lt;br /&gt;
:: https://bugzilla.redhat.com/show_bug.cgi?id=690586&lt;br /&gt;
&lt;br /&gt;
==[[Development_Team/Packaging|Development Team Packaging]]==&lt;br /&gt;
&lt;br /&gt;
==Sugar Bugs==&lt;br /&gt;
*Sugar on a Stick&lt;br /&gt;
:[[Sugar on a Stick Bugs]]&lt;br /&gt;
:[http://bugs.sugarlabs.org/query?status=assigned&amp;amp;status=new&amp;amp;status=reopened&amp;amp;groupdesc=1&amp;amp;group=milestone&amp;amp;component=Sugar+on+a+Stick+(SoaS)&amp;amp;order=priority&amp;amp;col=id&amp;amp;col=summary&amp;amp;col=component&amp;amp;col=status&amp;amp;col=type&amp;amp;col=priority&amp;amp;col=milestone&amp;amp;col=reporter&amp;amp;col=time&amp;amp;col=changetime Current Soas Bugs] satellit&lt;br /&gt;
*SoaS-Sugar&lt;br /&gt;
: http://bugs.sugarlabs.org/query?status=accepted&amp;amp;status=assigned&amp;amp;status=new&amp;amp;status=reopened&amp;amp;groupdesc=1&amp;amp;group=milestone&amp;amp;component=SoaS&amp;amp;order=priority&amp;amp;col=id&amp;amp;col=summary&amp;amp;col=component&amp;amp;col=status&amp;amp;col=type&amp;amp;col=priority&amp;amp;col=milestone&amp;amp;col=reporter&amp;amp;col=time&amp;amp;col=changetime (fgrose)&lt;br /&gt;
&lt;br /&gt;
*0.90-olpc &lt;br /&gt;
:http://bugs.sugarlabs.org/query?status=accepted&amp;amp;status=assigned&amp;amp;status=new&amp;amp;status=reopened&amp;amp;order=priority&amp;amp;col=id&amp;amp;col=summary&amp;amp;col=status&amp;amp;col=type&amp;amp;col=priority&amp;amp;col=milestone&amp;amp;col=component&amp;amp;keywords=~olpc-0.90 (pbrobinson)&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=EduJAM/2011&amp;diff=64160</id>
		<title>EduJAM/2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=EduJAM/2011&amp;diff=64160"/>
		<updated>2011-03-31T10:55:52Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Uruguay */ fix buquebus.com link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Translations}}&lt;br /&gt;
[[File:Edujam-logo-para-email-3.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Home page of the summit: http://edujam2011.ceibaljam.org&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This page is for planning the summit in Uruguay May 5th to 7th 2011.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Don&#039;t forget the [[Conozco Uruguay Tour|pre-summit tour Apr 30 - May 4/5,]] as well as post-summit codesprint May 8/9 onwards -- dates are final but details are evolving!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Main goals ==&lt;br /&gt;
* &#039;&#039;&#039;Focus on developers&#039;&#039;&#039;. It does not mean at all we&#039;re not concerned about educational aspects, but as a developers community we have huge challenges and the summit will be more of a working instance than a &amp;quot;reflection&amp;quot; instance.&lt;br /&gt;
* &#039;&#039;&#039;Exceed OLPC and Sugar&#039;&#039;&#039;. The developers community goes beyond OLPC and Sugar, and this could be a good instance for bringing &amp;quot;non-olpc organizations&amp;quot; to the conversation. &lt;br /&gt;
* &#039;&#039;&#039;Focus on South America&#039;&#039;&#039;. Bring as many south american developers as possible to Uruguay.&lt;br /&gt;
&lt;br /&gt;
== Program ==&lt;br /&gt;
A first sketch of the event (&#039;&#039;preliminary,&#039;&#039; [http://ceibaljam.org/drupal/?q=node/1127 see also update here!]) is as follows:&lt;br /&gt;
&lt;br /&gt;
Thu 5th:&lt;br /&gt;
* 18:00 Opening&lt;br /&gt;
&lt;br /&gt;
Fri 6th:&lt;br /&gt;
* 9:00 Keynote speaker(s)&lt;br /&gt;
* 10:30 Workshops and talks in 2 tracks (general topics)&lt;br /&gt;
* 13:00 Lunch&lt;br /&gt;
* 14:00 Workshops and discussions in 2 tracks: 1) Sugar activity development, and 2) [[Sugar Camp Q2 2011|Sugar future]]&lt;br /&gt;
* 19:00 Friday night social&lt;br /&gt;
&lt;br /&gt;
Sat 7th:&lt;br /&gt;
* 9:00 Deployment exchange&lt;br /&gt;
* 11:00 Unconference&lt;br /&gt;
* 13:00 Lunch&lt;br /&gt;
* 14:00 Unconference&lt;br /&gt;
* 18:00 Formal Event Closing&lt;br /&gt;
&lt;br /&gt;
Sun 8/9 ONWARDS: (Optional but encouraged! Separate venue/location possible...)&lt;br /&gt;
* 9:00 Hackfest/Codesprint til you drop!&lt;br /&gt;
&lt;br /&gt;
Program committee:&lt;br /&gt;
&lt;br /&gt;
* Andrés Ambrois&lt;br /&gt;
* Walter Bender&lt;br /&gt;
* Gabriel Eirea&lt;br /&gt;
* Pablo Flores&lt;br /&gt;
* Gonzalo Odiard&lt;br /&gt;
* Fernando Sansberro&lt;br /&gt;
&lt;br /&gt;
== Pre-Summit &amp;quot;Conozco Uruguay&amp;quot; Exploration Tour ==&lt;br /&gt;
We&#039;re organizing a set of in-person activities for those who want to know more about the Uruguayan/Ceibal experience, visiting different points of the country, meeting with families, teachers, etc.&lt;br /&gt;
&lt;br /&gt;
This will happen during the 5-6 days prior to the summit (from Saturday April 30th to Thursday May 5th) for independent and resilient travelers, committed to &amp;quot;anthropological&amp;quot; learning through patient exploration -- [[Conozco Uruguay Tour|details are emerging here!]]&lt;br /&gt;
&lt;br /&gt;
== Attendees ==&lt;br /&gt;
Attendees and possible attendees list in: http://ceibaljam.org/drupal/?q=node/1108&amp;lt;br&amp;gt;&lt;br /&gt;
If you want to attend, please write us: edujam2011@ceibaljam.org&lt;br /&gt;
&lt;br /&gt;
Including Volunteer Organizers: Martín Abente, Walter Bender, Gabriel Eirea, David Farning, Pablo Flores, [[user:Holt|Adam Holt]], Bernie Innocenti, Aleksey Lim, Anish Mangal, Gonzalo Odiard, [[user:aa|Andrés Ambrois]]&lt;br /&gt;
&lt;br /&gt;
== Accommodation ==&lt;br /&gt;
We&#039;ll put here some information about possible places for staying. At the same time we&#039;ll make a volunteers hosting program, so Uruguayan volunteers can host some of the attendees. More information soon.&lt;br /&gt;
&lt;br /&gt;
Uruguay (generally) uses [http://treehouse.ofb.net/go/en/voltage/Uruguay 220V European] [http://www.adaptelec.com/index.php?main_page=document_general_info&amp;amp;products_id=252 electrical outlets] so please consider bringing a small converter.&lt;br /&gt;
&lt;br /&gt;
Wifi access will be sought where possible, but not guaranteed.&lt;br /&gt;
&lt;br /&gt;
== Registration ==&lt;br /&gt;
[http://ceibaljam.org/drupal/?q=edujam2011_en Registration is now Open!]&lt;br /&gt;
&lt;br /&gt;
As explained therein, pricing is $100, with confirmed volunteers/students paying $30 or $10.  Attendance will likely be limited to about 100 attendees maximum.&lt;br /&gt;
&lt;br /&gt;
Flight prices will rise, so we strongly encourage you to book your flight to Montevideo (MVD) &amp;amp; register today!&lt;br /&gt;
&lt;br /&gt;
== Uruguay ==&lt;br /&gt;
&lt;br /&gt;
Visas are [http://worldtravelguide.net/uruguay/passport-visa not required] for most US, Canada, Europe, Australia citizens.&lt;br /&gt;
&lt;br /&gt;
Direct flights to Montevideo (Carrasco Airport) from:&lt;br /&gt;
* US: Miami&lt;br /&gt;
* Europe: Madrid&lt;br /&gt;
* Most of South America&lt;br /&gt;
* Nearby hubs: Buenos Aires, Sao Paulo, Santiago&lt;br /&gt;
There are also nice ferries from Buenos Aires: http://www.buquebus.com/&lt;br /&gt;
&lt;br /&gt;
An airport departure tax of $30+ may be charged upon leaving Uruguay, if not pre-paid within your flight ticket.&lt;br /&gt;
&lt;br /&gt;
Touristic information: http://www.turismo.gub.uy&lt;br /&gt;
&lt;br /&gt;
Don&#039;t forget to register for &amp;quot;Conozco Uruguay&amp;quot;, our [[Conozco Uruguay Tour|pre-summit eduTRIP!]] (Saturday April 30 - Thursday May 5)&lt;br /&gt;
&lt;br /&gt;
==Discussion==&lt;br /&gt;
&lt;br /&gt;
Caryl Bigenho has posted some really great suggestions &amp;amp; topics on the [[Talk:Uruguay_Summit_2011|Talk Page]] -- eg. she started with &amp;quot;fun&amp;quot; activities for teachers, students, and parents to participate in alongside software architects -- please join her to [[Talk:Uruguay_Summit_2011|share your own ideas, for things you&#039;d like to do at EduJAM!]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=60213</id>
		<title>Development Team/Low-level Activity API</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Development_Team/Low-level_Activity_API&amp;diff=60213"/>
		<updated>2010-12-14T18:51:22Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Querying */ add query syntax reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Developers}}{{TOCright}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sugar activities are usually written in Python using the [http://api.sugarlabs.org/ Python Activity API]. This page documents the underlying mechanism that all activities need to conform to. Activities can be written in any language, as long as it can connect to D-Bus and provide an X11 interface. The discussion below tries to be language-agnostic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This documentation effort was started by [[User:Bert|Bert]] on the [http://wiki.laptop.org/go/Low-level_Activity_API OLPC wiki] while implementing the [[olpc:Squeak|Squeak]]-based [[Activities/Etoys|Etoys]] activity. Please fill in missing pieces and correct mistakes!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[olpc:Activity Development Alternatives]] for an overview of various ways to develop activities.&lt;br /&gt;
&lt;br /&gt;
As Sugar evolves to become compatible with ordinary X11 programs, and as services like collaboration migrate into generic X11 desktops, this document will become less and less relevant.  All the special rules for &amp;quot;Sugar Activities&amp;quot; will fall by the wayside, because any X11 program will be usable with Sugar.  This will greatly simplify both the job of Activity authors, and the usefulness of Sugar-based computers (which will have access to thousands of X &amp;quot;applications&amp;quot; that have never heard of Sugar and never will).&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
An Activity is basically a regular X11 program which communicates with the special Sugar services via D-Bus.&lt;br /&gt;
&lt;br /&gt;
The [[Development Team/Almanac/Activity Bundles|Activity bundle]] specifies an executable. For each [[#Activity Instance|activity instance]], that executable is run with arguments specifying the bundle id (taken from the bundle) and activity id (generated by Sugar). The instance opens an X window, putting these ids into window [[#X Properties|properties]]. It also needs to provide a D-Bus [[#D-Bus Methods|service]] to receive messages from Sugar. An activity must retrieve and store its state in the [[#Datastore|datastore]], implement [[#Presence|sharing]] on the mesh network, and be [[#Security|security]] compliant.&lt;br /&gt;
&lt;br /&gt;
==Activity Life Cycle==&lt;br /&gt;
Please see [[Human Interface Guidelines/Activities/Activity Basics|Activity Basics]] for the user&#039;s point of view. The programmer&#039;s point of view is outlined here, and detailed in the following sections:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Start Up&#039;&#039;&#039;&lt;br /&gt;
# The activity is executed.&lt;br /&gt;
# It creates a D-Bus service to receive method calls from the Sugar shell. &lt;br /&gt;
# It creates an X11 window with special properties so the Sugar shell can associate an activity with its window.&lt;br /&gt;
# If an object id was passed on the command line, the activity loads that object from the Datastore. Otherwise, it creates a new Datastore object.&lt;br /&gt;
# The activity asks the Presence Service to find out if it is shared. If so, it joins the shared activity.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Operation&#039;&#039;&#039;&lt;br /&gt;
# The activity continuously handles X11 user input, as well as D-Bus messages from the Sugar shell, or signals from other sources like the Presence Service.&lt;br /&gt;
# Whenever the state of the activity was altered significantly, it should update its Datastore object to prevent data loss on an unexpected shutdown.&lt;br /&gt;
# If the user indicates wanting to share the activity, it has to announce this to the Presence Service.&lt;br /&gt;
# If the view-source key is pressed, some meta-action about the activity should be invoked, like showing its source code.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shut Down&#039;&#039;&#039;&lt;br /&gt;
# When the activity window is closed, it updates its Datastore object with its current state.&lt;br /&gt;
# It leaves the shared activity (if shared),&lt;br /&gt;
# and then quits.&lt;br /&gt;
&lt;br /&gt;
=Activity Instance=&lt;br /&gt;
&lt;br /&gt;
When the activity instance is executed, the current working directory will be set to the bundle directory (e.g., ~/Activities/MyActivity.activity) so resource files can be accessed using relative paths. Also, its &amp;quot;bin&amp;quot; subdirectory is added to the PATH.&lt;br /&gt;
&lt;br /&gt;
==Command Line Arguments==&lt;br /&gt;
&lt;br /&gt;
The following arguments are passed to the executable:&lt;br /&gt;
&lt;br /&gt;
; -b, --bundle-id : Identifier of the activity bundle. Must be made available as [[#X Property|window property]].&lt;br /&gt;
; -a, --activity-id : Unique identifier of the activity instance. Must be made available as [[#X Property|window property]], and is used to create the [[#D-Bus Methods|D-Bus service]].&lt;br /&gt;
; -o, --object-id   : (optional) Identity of the journal object associated with the activity instance. When you resume an activity from the journal the object id will be passed in (see [[#Datastore|datastore]]). &lt;br /&gt;
; -u, --uri         : (optional) URI associated with the activity. Used when opening an external file or resource in the activity, rather than a journal object (downloads stored on the file system for example or web pages).&lt;br /&gt;
&lt;br /&gt;
==Environment Variables==&lt;br /&gt;
&lt;br /&gt;
Some environment variables are setup before the activity is launched:&lt;br /&gt;
&lt;br /&gt;
 SUGAR_ACTIVITY_ROOT&lt;br /&gt;
&lt;br /&gt;
Writable space for the activity, see [[#Security|security]]. Activities are prohibited from writing anywhere else in the file system.&lt;br /&gt;
&lt;br /&gt;
 SUGAR_BUNDLE_PATH&lt;br /&gt;
&lt;br /&gt;
Path to the current activity bundle (e.g., /usr/share/activities/MyActivity.activity or ~/Activities/MyActivity.activity). This is also the current working directory when the activity is started, so relative paths can be used to access files inside the bundle, rather than constructing absolute paths using this variable.&lt;br /&gt;
&lt;br /&gt;
==X Properties==&lt;br /&gt;
The activity instance needs to set some properties on its top-level window, &#039;&#039;&#039;before&#039;&#039;&#039; the window is shown on the screen (see [http://dev.laptop.org/ticket/5271 #5271]):&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_BUNDLE_ID &lt;br /&gt;
&lt;br /&gt;
The bundle id (e.g., &amp;lt;tt&amp;gt;my.organization.MyActivity&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
 _SUGAR_ACTIVITY_ID &lt;br /&gt;
&lt;br /&gt;
The activity id (e.g., &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt;) of type &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; as passed on the [[#Command Line Arguments|command line]].&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;The above properties need to be on the window before it pops up. This is easy when programming with raw libX11, but often difficult with high-level toolkits. E.g., in GTK you can use the &amp;quot;realize&amp;quot; event. The toolkit is likely to create and pop up the window in one operation, so you don&#039;t get a chance to set the properties. A workable solution is to piggyback on a function within the toolkit. For example, you can implement XChangeProperty in your activity. Using dlsym() with the RTLD_NEXT flag, you can obtain a function pointer to the normal XChangeProperty function in libX11. Your implementation normally just calls that. The first time your implementation is called though, it also sets up the sugar-specific properties. Essentially you are supplying a callback function to a toolkit that was never intended to call one. &#039;&#039;Once [http://dev.laptop.org/ticket/5271 #5271] is settled, this hack is not necessary anymore&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, some Window Manager hints need to be set:&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_NAME&lt;br /&gt;
&lt;br /&gt;
should be set to the current activity title. It usually corresponds to the title which is displayed in the journal and advertised on the network for shared activities. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511086 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
 _NET_WM_PID&lt;br /&gt;
&lt;br /&gt;
must be set to the activity&#039;s process id so the shell can associate memory usage with an activity. See [http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#id2511925 Freedesktop specification].&lt;br /&gt;
&lt;br /&gt;
==D-Bus Methods==&lt;br /&gt;
An activity instance needs to create a D-Bus service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.Activity6f7f3acacca87886332f50bdd522d805f0abbf1f           # no dot after Activity!&lt;br /&gt;
 Object path:  /org/laptop/Activity/6f7f3acacca87886332f50bdd522d805f0abbf1f&lt;br /&gt;
 Interface:    org.laptop.Activity&lt;br /&gt;
&lt;br /&gt;
(where &amp;lt;tt&amp;gt;6f7f3acacca87886332f50bdd522d805f0abbf1f&amp;lt;/tt&amp;gt; is the activity id as passed on the cmd line)&lt;br /&gt;
&lt;br /&gt;
It must support the following methods:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.SetActive(b: active)&lt;br /&gt;
&lt;br /&gt;
Activate or passivate an activity. This is sent when switching activities, there is only one active activity at a time, all others are passive. A passive activity must immediately release resources like sound, camera etc. Also it should prepare for being killed without warning at any time in the future (see [[olpc:OOM|OOM]]) by auto-saving to the datastore.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.Invite(s: buddy_key)&lt;br /&gt;
&lt;br /&gt;
If not yet shared, share this activity privately because the user chose &amp;quot;invite&amp;quot; from the mesh view. Then, invite the buddy (see [[#Inviting|below]]).&lt;br /&gt;
&lt;br /&gt;
The following methods are &#039;&#039;&#039;optional&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.HandleViewSource()&lt;br /&gt;
&lt;br /&gt;
The user wants to view the source. If this method does not answer an error, the activity will handle viewing the source code itself, otherwise Sugar will show the source.&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Activity.GetDocumentPath():s&lt;br /&gt;
&lt;br /&gt;
Answer the path of a document source file to view, in addition to the activity bundle itself. Sugar will delete that document when the view-source interface is closed. This method is only called when Sugar handles the source viewing.&lt;br /&gt;
&lt;br /&gt;
== Session ==&lt;br /&gt;
&lt;br /&gt;
To communicate to an activity when it needs to save data and quit, we use the [http://www.xfree.org/current/xsmp.pdf X Session management protocol]. The part of the protocol which deals with application restarting is not used and we don&#039;t plan to implement it.&lt;br /&gt;
&lt;br /&gt;
In the Glucose 0.84 release cycle we are planning do add support for a D-Bus based protocol which is currently being developed for the GNOME desktop. You can read about it on this [http://bugzilla.gnome.org/show_bug.cgi?id=535829 bugzilla report].&lt;br /&gt;
&lt;br /&gt;
=Datastore=&lt;br /&gt;
&lt;br /&gt;
An Activity instance must store its complete state in the central datastore so it appears in the Journal and can be resumed later. It needs to connect to the datastore service:&lt;br /&gt;
&lt;br /&gt;
 Service name: org.laptop.sugar.DataStore&lt;br /&gt;
 Object path:  /org/laptop/sugar/DataStore&lt;br /&gt;
 Interface:    org.laptop.sugar.DataStore&lt;br /&gt;
&lt;br /&gt;
==Meta Data==&lt;br /&gt;
An item in the datastore is referenced by an object_id, it has a dictionary of properties, and possibly a file. The properties have String keys but Variant values. Here are a few properties:&lt;br /&gt;
&lt;br /&gt;
 &#039;activity&#039;:          &#039;my.organization.MyActivity&#039;             # bundle id (determines icon and default activity)&lt;br /&gt;
 &#039;activity_id&#039;:       &#039;6f7f3acacca87886332f50bdd522d805f0abbf1f&#039;&lt;br /&gt;
 &#039;title&#039;:             &#039;My new project&#039;                         # as shown in journal&lt;br /&gt;
 &#039;title_set_by_user&#039;: &#039;0&#039;                                      # &#039;1&#039; if not default title&lt;br /&gt;
 &#039;keep&#039;:              &#039;0&#039;                                      # &#039;1&#039; if marked as &amp;quot;favorite&amp;quot; (star)&lt;br /&gt;
 &#039;ctime&#039;:             &#039;1972-05-12T18:41:08&#039;                    # created (local time)&lt;br /&gt;
 &#039;mtime&#039;:             &#039;2007-06-16T03:42:33&#039;                    # modified (local time), deprecated but still used internally so must be present&lt;br /&gt;
 &#039;timestamp&#039;:         1192715145                               # modified (UTC), in seconds since the UNIX epoch, must be present&lt;br /&gt;
 &#039;preview&#039;:           ByteArray(png file data, 300x225 px)&lt;br /&gt;
 &#039;icon-color&#039;:        &#039;#ff0000,#ffff00&#039;                        # owner buddy or shared activity color&lt;br /&gt;
 &#039;mime_type&#039;:         &#039;application/x-my-activity&#039;&lt;br /&gt;
 &#039;share-scope&#039;:                                                # if shared&lt;br /&gt;
 &#039;buddies&#039;:           &#039;{}&#039;                                     # buddies in a shared activity as JSON&lt;br /&gt;
 &#039;description&#039;:       &#039;some longer text&#039;                       # description editable in journal detail view&lt;br /&gt;
 &#039;tags&#039;:              &#039;one two&#039;                                # tags editable in journal detail view&lt;br /&gt;
 &#039;something:text&#039;:    &#039;text I want to be indexed&#039;              # properties with key ending in &amp;quot;:text&amp;quot; will be searched in fulltext search&lt;br /&gt;
 &#039;checksum&#039;:                                                   # md5 hash of file, created by DS, do not set or modify&lt;br /&gt;
 &#039;my.organization.MyActivity.myProperty&#039;                       # private property, prefixed with activity name to avoid name clashes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Due to bug [http://dev.laptop.org/ticket/4662 #4662] only some known properties are retained! The list is at the bottom of [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/625c4f13624d52abdc9c1cc26f9b63342ac400c7/src/olpc/datastore/model.py#line379 datastore/model.py] (fixed in Sugar 0.83)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And custom properties must have String values for now (bug [http://dev.laptop.org/ticket/5134 #5134]).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;And since Sugar 0.83 all former String values are now stored and returned as Arrays of Bytes. You can still set them as Strings.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Keeping and Resuming==&lt;br /&gt;
&lt;br /&gt;
To create an item in the datastore, call create():&lt;br /&gt;
&lt;br /&gt;
 object_id = datastore.create(properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
The metadata properties are a dictionary (type &amp;quot;a{sv}&amp;quot;) containing (at least) the entries mentioned above. If filename is not empty, the file will be moved or copied to the datastore, depending on the transfer_ownership flag. The activity should delete the file once the call completes (if transfer_ownership was false). Otherwise (if transfer_ownership was true) the datastore will remove the file. &#039;&#039;For this to work under rainbow you must place the file in the [[#Writable Directories|&amp;quot;instance&amp;quot; directory]].&#039;&#039; The returned id will be a string like &#039;4543af91-7be9-404e-b2f1-3e27cb15a15d&#039;. &lt;br /&gt;
&lt;br /&gt;
To update an item use update():&lt;br /&gt;
&lt;br /&gt;
 datastore.update(object_id, properties, filename, transfer_ownership)&lt;br /&gt;
&lt;br /&gt;
Again, if a filename was given and transfer_ownership is false, the activity is responsible for deleting the file after the call returns. &lt;br /&gt;
&lt;br /&gt;
To retrieve an object&#039;s properties and file:&lt;br /&gt;
&lt;br /&gt;
 properties = datastore.get_properties(object_id)&lt;br /&gt;
 filename = datastore.get_filename(object_id)&lt;br /&gt;
&lt;br /&gt;
The returned temp file should be deleted by the activity as soon as possible, latest when the activity quits.&lt;br /&gt;
&lt;br /&gt;
The metadata properties need to be preserved and stored again when updating an entry. An activity should also track updates to the properties made in the Journal while editing the datastore object. For this it should subscribe to the Updated signal:&lt;br /&gt;
&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;small&amp;gt;An efficient way to do this is registering a DBus match like &amp;lt;tt&amp;gt;path=&#039;/org/laptop/sugar/DataStore&#039;, member=&#039;Updated&#039;, interface=&#039;org.laptop.sugar.DataStore&#039;, type=&#039;signal&#039;, arg0=&#039;&amp;lt;i&amp;gt;objectId&amp;lt;/i&amp;gt;&#039;&amp;lt;/tt&amp;gt; --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querying==&lt;br /&gt;
&lt;br /&gt;
Activities may query the datastore:&lt;br /&gt;
&lt;br /&gt;
 (results,count) = datastore.find(query, properties)&lt;br /&gt;
&lt;br /&gt;
It returns the matching object&#039;s metadata as array of dictionaries, and a count of matching items (the array may have fewer items if the query was limited). In addition to the usual metadata items, each dictionary will include the object id at key &#039;uid&#039;, the mountpoint of the item at key &#039;mountpoint&#039;, and possibly a &#039;filename&#039; if requested.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;properties&#039;&#039;&#039; argument is an array of strings. It defines which keys to include in the results. You should only specify the keys you actually need. If you pass an empty array here, all the metadata would be returned, which for a Journal with hundreds of entries and previews could amount to multiple megabytes of data. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;query&#039;&#039;&#039; argument is a dictionary. If empty, all the datastore&#039;s entries will be returned, but again, you should avoid that. The key-value pairs specify the value (or array of values, or dictionary specifying range) for a specific property, e.g.:&lt;br /&gt;
: &#039;title&#039; = &#039;First Project&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;mime_type&#039; = [&#039;image/png&#039;, &#039;image/jpeg&#039;]&lt;br /&gt;
: &#039;mtime&#039; = {&#039;start&#039; = &#039;2007-07-01T00:00:00&#039;, &#039;end&#039; = &#039;2007-08-01T00:00:00&#039;}&lt;br /&gt;
A few specific keys adjust the query:&lt;br /&gt;
: &#039;query&#039;: fulltext search term (supports some [http://xapian.org/docs/queryparser.html special operators])&lt;br /&gt;
: &#039;order_by&#039;: sort key (or array of keys) to order results by, to reverse order use &#039;-key&#039; &amp;lt;i&amp;gt;(but see note below)&amp;lt;/i&amp;gt;&lt;br /&gt;
: &#039;limit&#039;, &#039;offset&#039;: return only limit results starting at offset&lt;br /&gt;
: &#039;mountpoints&#039;: array of [[#Mount Points|mountpoint ids]] to search (or all if not specified)&lt;br /&gt;
: &#039;include_files&#039;: if true, generate files as if get_filename() had been called for each item. In results, a property &#039;filename&#039; will be added.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;NOTE: In Sugar 0.82 you cannot search for &#039;uid&#039;. Since Sugar 0.84 only very few keys are supported in the query (&#039;uid&#039;, &#039;activity&#039;, &#039;activity_id&#039;, &#039;mime_type&#039;,  and &#039;keep&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line32 here]). Other keys are ignored so you may get back more results than expected. Results are ordered by timestamp by default. Sort keys are limited, too (none in 0.84, in 0.86 &#039;timestamp&#039; and &#039;title&#039;, see [http://git.sugarlabs.org/projects/sugar-datastore/repos/mainline/blobs/master/src/carquinyol/indexstore.py#line266 here]).&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also retrieve an array of unique values for a field:&lt;br /&gt;
&lt;br /&gt;
 values = datastore.get_uniquevaluesfor(property, query)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NOTE: currently (2007-07-25) the query is ignored in this call, it looks for all values in all entries. And in more recent Sugar versions, the only property allowed is &#039;activity&#039;.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Watching==&lt;br /&gt;
&lt;br /&gt;
To keep cached information in your activity up-to-date, you can subscribe to these signals:&lt;br /&gt;
&lt;br /&gt;
 datastore.Created(object_id)&lt;br /&gt;
 datastore.Updated(object_id)&lt;br /&gt;
 datastore.Deleted(object_id)&lt;br /&gt;
&lt;br /&gt;
E.g. if you display a document title in your activity, and the user changes that entry in the Journal while your activity is running, you can use the Updated signal to reflect that change. Otherwise, when you save the document, it will overwrite the title set by the user. &lt;br /&gt;
&lt;br /&gt;
Similarly, if you display a list of Journal entries in your activity, it would have to be updated in response to the Created and Deleted signals.&lt;br /&gt;
&lt;br /&gt;
==Progress Display==&lt;br /&gt;
&lt;br /&gt;
To add a progress bar to a Journal entry (like the Browse activity does while downloading files), create an entry with a &amp;quot;progress&amp;quot; property in the meta data. The value is the percentage done (0 to 100). The file cannot actually be stored incrementally in the datastore, it needs to be saved to a temp file first. But the entry metadata can be updated continuously to inform the user of progress while creating the temp file (by not giving a filename yet in the update() call). Once the temp file is complete, it can be checked-in as usual. The user can cancel by clicking the x icon next to the progress bar. This deletes the entry, so you need to watch for the datastore&#039;s &amp;quot;Deleted(id)&amp;quot; signal.&lt;br /&gt;
&lt;br /&gt;
 meta = ...                                     # regular metadata&lt;br /&gt;
 meta[&amp;quot;progress&amp;quot;] = 0&lt;br /&gt;
 id = datastore.create(meta, &amp;quot;&amp;quot;)                # create with progress bar&lt;br /&gt;
 while (done() &amp;lt; 100) {&lt;br /&gt;
     if (got_signal(datastore, &amp;quot;Deleted&amp;quot;, id))&lt;br /&gt;
         return user_cancelled();&lt;br /&gt;
     write_to(tmpfile)&lt;br /&gt;
     meta[&#039;progress&#039;] = done()&lt;br /&gt;
     datastore.update(id, meta, &amp;quot;&amp;quot;)             # update progress bar&lt;br /&gt;
 }&lt;br /&gt;
 meta.deleteKey(&amp;quot;progress&amp;quot;)&lt;br /&gt;
 datastore.update(id, meta, tmpfile.name)       # check-in file, remove progress bar&lt;br /&gt;
&lt;br /&gt;
==Journal UI==&lt;br /&gt;
The Journal activity provides a D-Bus service to allow activities to bring up an object chooser dialog, focus searches etc.:&lt;br /&gt;
 Service name: org.laptop.Journal&lt;br /&gt;
 Object path:  /org/laptop/Journal&lt;br /&gt;
 Interface:    org.laptop.Journal&lt;br /&gt;
===Choosing Objects===&lt;br /&gt;
Call this method to bring up the Chooser dialog (which looks like a small journal overlayed on your activity):&lt;br /&gt;
 chooser_id = org.laptop.Journal.ChooseObject(xid, what_filter)                      # only xid arg supported in Sugar 0.82!&lt;br /&gt;
The xid should be your activity&#039;s X window handle, or &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;. The filter says what type of Journal entries is preselected in the drop-down menu (&#039;&#039;this parameter was added in Sugar 0.83&#039;&#039;). It&#039;s a string containing either a bundle id (e.g., &amp;lt;tt&amp;gt;&#039;my.organization.MyActivity&#039;&amp;lt;/tt&amp;gt;), or one of the generic data types (&amp;lt;tt&amp;gt;&#039;Text&#039;, &#039;Image&#039;, &#039;Video&#039;, &#039;Audio&#039;, &#039;Link&#039;&amp;lt;/tt&amp;gt; [http://git.sugarlabs.org/projects/sugar-base/repos/mainline/blobs/master/src/sugar/mime.py#line32 definition]), or an empty string for no filter. The call returns immediately with a string chooser_id. You need to watch these signals which get emitted when an item is chosen or the dialog is canceled:&lt;br /&gt;
 ObjectChooserResponse(chooser_id, object_id)&lt;br /&gt;
 ObjectChooserCancelled(chooser_id)&lt;br /&gt;
The object_id received in an ObjectChooserResponse signal then can be used to open the corresponding [[#Keeping and Resuming|datastore object]].&lt;br /&gt;
&lt;br /&gt;
===Focusing Objects===&lt;br /&gt;
The Journal activity allows an activitiy to &amp;quot;focus&amp;quot; an object, so the user can immediately open it (this is currently the only way to have one activity &amp;quot;launch&amp;quot; a different activity).&lt;br /&gt;
&lt;br /&gt;
 org.laptop.Journal.ShowObject(object_id)&lt;br /&gt;
&lt;br /&gt;
Switches to the Journal activity and shows the selected object.&lt;br /&gt;
&lt;br /&gt;
This can be used to, e.g., open a URL (create a URL object in the journal then call this) or to view source code (store the source code as text file in the journal then call ShowObject() on it).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;To focus on multiple objects: &amp;lt;code&amp;gt;org.laptop.Journal.FocusSearch(query)&amp;lt;/code&amp;gt;&amp;lt;/s&amp;gt; &#039;&#039;Removed in Sugar 0.83&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Mount Points==&lt;br /&gt;
Devices are represented as mount points in the datastore. If no mountpoint is explicitly specified, the main datastore (Journal) is used.&lt;br /&gt;
&lt;br /&gt;
   mounts = datastore.mounts()&lt;br /&gt;
&lt;br /&gt;
Returns an array of mount point descriptors where each descriptor is a dictionary containing at least the following keys:&lt;br /&gt;
:&#039;id&#039;: the id used to refer explicitly to the mount point&lt;br /&gt;
:&#039;title&#039;: Human readable identifier for the mountpoint &#039;&#039;(in Sugar 0.82, just the uri)&#039;&#039;&lt;br /&gt;
:&#039;uri&#039;: The uri which triggered the mount&lt;br /&gt;
&lt;br /&gt;
Mount points can be specified when creating an object (using a &#039;mountpoint&#039; key and id value in the properties), and when querying the datastore (by adding a &#039;mountpoints&#039; query option).&lt;br /&gt;
&lt;br /&gt;
Large files to be stored on an external device should be placed at the uri of the mount point (see [[#External Media|external media]]).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; &#039;&#039;This only works as described in Sugar up to 0.82. The functions do exist in later Sugar versions, but do not return useful data.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
&lt;br /&gt;
Activities are isolated from each other and from the &amp;quot;olpc&amp;quot; user. They do not have the same permissions as you would expect in a non-restricted Linux environment (see [[olpc:OLPC Bitfrost|Bitfrost]] and [[olpc:Rainbow|Rainbow]]). In particular, they can &#039;&#039;&#039;not&#039;&#039;&#039; write in the /home/olpc directory!&lt;br /&gt;
&lt;br /&gt;
== Users and Groups ==&lt;br /&gt;
&lt;br /&gt;
While Sugar runs as user &amp;quot;olpc&amp;quot;, activities do &#039;&#039;&#039;not&#039;&#039;&#039; (the [[olpc:Terminal|Terminal]] activity as a maintenance tool is an exception).&lt;br /&gt;
&lt;br /&gt;
Instead, each activity instance is run with a unique user id.  That is, a new anonymous user is created when the user clicks an activity icon, and the [[olpc:Rainbow|Rainbow]] demon runs the activity under that user. &lt;br /&gt;
&lt;br /&gt;
All instance of the same activity get the same unique group id. That is, a new anonymous group is created when the activity is run for the first time, each subsequent activity launch will use the same group id. This means files to be shared for all instances of an activity must be made group-accessible.&lt;br /&gt;
&lt;br /&gt;
== File Access ==&lt;br /&gt;
&lt;br /&gt;
=== Home Directory ===&lt;br /&gt;
&lt;br /&gt;
Since each activity is run as a different user, it gets a different home directory on each invocation. In release 8.2, the home directory for an activity equals the $SUGAR_ACTIVITY_ROOT/instance/ directory  (see below). For data such as config files to survive and be accessible by all future activity invocations, they must not be stored in $HOME but rather $SUGAR_ACTIVITY_ROOT/data/ should be used.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;small&amp;gt;Hint: A trick to help porting legacy software which expects its config files to be in the home directory is to export HOME=$SUGAR_ACTIVITY_ROOT/data in an activity&#039;s launch script. --[[User:Bert|Bert]]&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Writable Directories ===&lt;br /&gt;
All writing to the file system is restricted to subdirectories of the path given in the SUGAR_ACTIVITY_ROOT environment variable. This directory has three subdirectories with different policies:&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/data/: This directory is used similar to a traditional home directory, for persistent activity data such as configuration files. Make sure files in there are group readable and writable (see [[#Users and Groups|users and groups]]). The directory itself is group-writable. Files stored here will survive reboots and OS upgrades.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/tmp/: This directory is used similar to a /tmp directory, being backed by RAM. It may be as small as 1 MB. This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die). This directory is &#039;&#039;only&#039;&#039; accessible to the activity and its children; not even to Sugar.&lt;br /&gt;
&lt;br /&gt;
;$SUGAR_ACTIVITY_ROOT/instance/: This directory is used similar to a /var/tmp directory, being backed by flash rather than by RAM. It is unique per instance. It is used for transfer to and from the datastore (see [[#Keeping and Resuming|keeping and resuming]]). This directory is deleted when the activity exits (specifically,  as soon as all children of the activity&#039;s first process die)&lt;br /&gt;
&lt;br /&gt;
As of version 8.2, all the activity root directories are created in /home/olpc/isolation and can be examined there with the Terminal activity. However, activities MUST use the $SUGAR_ACTIVITY_ROOT variable because the isolation directory layout is expected to change.&lt;br /&gt;
&lt;br /&gt;
=== Concurrency ===&lt;br /&gt;
&lt;br /&gt;
Multiple instances of an activity may communicate with one another through their shared &#039;data&#039; directory; however, since each instance runs as a different user, [[olpc:Concurrent activity instances|some care must be taken]] ([http://dev.laptop.org/ticket/5476 #5476]) when sending messages to other activities through this shared medium.&lt;br /&gt;
&lt;br /&gt;
=== External Media ===&lt;br /&gt;
&lt;br /&gt;
External media (USB drives, SD cards) are auto-mounted by the Journal and appear in /media/*. No access restrictions are applied currently (up to release 8.2). If activities use these external media directly (rather than through the Journal, see [[#Mount Points|mount points]]), they need to take care of ensuring data integrity since the user may (and will) remove the medium at any time.&lt;br /&gt;
&lt;br /&gt;
== Signing ==&lt;br /&gt;
&lt;br /&gt;
An activity will have to be cryptographically signed to allow secure activity upgrades once they are on the machines. Tools for this will be provided soon. See discussion of [[Development Team/Almanac/Activity Bundles#Bundle Structure|contents.sig]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Permissions Declarations ==&lt;br /&gt;
&lt;br /&gt;
Permission declarations will enumerate which special permissions (camera access? microphone access? non-Tubes network access? etc.) your activity may need for its normal operation. See  [[Development Team/Almanac/Activity Bundles#activity/permissions.info|permissions.info]] and generally [[olpc:OLPC Bitfrost|Bitfrost]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;to be detailed&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Presence=&lt;br /&gt;
&lt;br /&gt;
Collaboration plays a large role in Sugar. Still, the presence and sharing APIs are still somewhat rough. There are attempts to explain sharing, see [[olpc:Activity sharing|Activity sharing]]. The following are the bare essentials.&lt;br /&gt;
&lt;br /&gt;
==General==&lt;br /&gt;
&lt;br /&gt;
Activities must support sharing using the [[olpc:Presence Service D-Bus API|Presence Service]] (PS). It is accessible on the D-Bus:&lt;br /&gt;
&lt;br /&gt;
 Service:     org.laptop.Sugar.Presence&lt;br /&gt;
 Interface:   org.laptop.Sugar.Presence&lt;br /&gt;
 Object Path: /org/laptop/Sugar/Presence&lt;br /&gt;
&lt;br /&gt;
===Sharing===&lt;br /&gt;
&lt;br /&gt;
If the activity was not yet shared but the user clicked the Share button, sharing is initiated by calling ShareActivity():&lt;br /&gt;
&lt;br /&gt;
 activity = PS.ShareActivity(activity_id, bundle_id, name, properties)&lt;br /&gt;
&lt;br /&gt;
The bundle id is used for the icon and to launch the same activity when someone joins it. The name will be shown in the mesh view and should generally be the same as the title of the datastore object (see above). The properties argument is not used currently (but see [http://dev.laptop.org/ticket/4660 #4660]) and should be an empty dictionary.&lt;br /&gt;
&lt;br /&gt;
Note that sharing will be private (invitation-only) by default, that is, the icon will not be visible in the mesh. To share publicly, set the &#039;private&#039; property to False:&lt;br /&gt;
&lt;br /&gt;
 activity.SetProperties({&#039;private&#039;: False})&lt;br /&gt;
&lt;br /&gt;
===Inviting===&lt;br /&gt;
Another way of starting a shared session is by inviting a buddy from the mesh view. The Invite() method of the activity is called (see [[#D-Bus_Methods|above]]). Then the activity should be shared privately, and the buddy must be invited using the key that was passed to Invite():&lt;br /&gt;
&lt;br /&gt;
 buddy = PS.GetBuddyByPublicKey(buddy_key)&lt;br /&gt;
 activity.Invite(buddy, message)&lt;br /&gt;
&lt;br /&gt;
===Joining===&lt;br /&gt;
&lt;br /&gt;
When launching, the PS must be consulted to see if this instance was shared by someone else, meaning it was launched by the user is trying to join it:&lt;br /&gt;
&lt;br /&gt;
 activity = PS.GetActivityById(activity_id)&lt;br /&gt;
&lt;br /&gt;
This yields an error if this instance (identified by its activity id) was not shared, in which case a regular non-shared startup should be performed. Otherwise, the activity object held by the PS is returned, and this activity instance needs to join:&lt;br /&gt;
&lt;br /&gt;
 activity.Join()&lt;br /&gt;
&lt;br /&gt;
It should continue by establishing a communication channel with the originating instance (see below)&lt;br /&gt;
&lt;br /&gt;
=== Leaving ===&lt;br /&gt;
&lt;br /&gt;
To leave a shared activity (e.g. because it is closing) you need to inform the PS:&lt;br /&gt;
&lt;br /&gt;
 activity.Leave()&lt;br /&gt;
&lt;br /&gt;
==Buddies==&lt;br /&gt;
&lt;br /&gt;
The activity object created by either sharing the current activity or joining an existing activity is used to establish means of communication between these instances. The joined XOs can be accessed to start communicating with them:&lt;br /&gt;
&lt;br /&gt;
 buddies = activity.GetJoinedBuddies()&lt;br /&gt;
&lt;br /&gt;
To get notified of buddies joining or leaving, listen to these signals:&lt;br /&gt;
&lt;br /&gt;
 BuddyJoined (o: buddy)&lt;br /&gt;
 BuddyLeft (o: buddy)&lt;br /&gt;
&lt;br /&gt;
==Tubes==&lt;br /&gt;
&amp;quot;Tubes&amp;quot; are the transport medium of choice on the XO, provided by the [http://telepathy.freedesktop.org/ Telepathy] framework. There are &amp;quot;D-Bus Tubes&amp;quot; allowing remote D-Bus calls, and &amp;quot;Stream Tubes&amp;quot; which forward sockets (similar to ssh forwarding). Tubes are collected in a &amp;quot;Channel&amp;quot;, and channels are associated with a &amp;quot;room&amp;quot;, one per shared activity instance.&lt;br /&gt;
&lt;br /&gt;
First, get the Telepathy connection from the shared activity object:&lt;br /&gt;
&lt;br /&gt;
  (tp_service, tp_connection, channels) = activity.GetChannels()&lt;br /&gt;
&lt;br /&gt;
where tp_service and tp_connection is the D-Bus service name and object path for the Telepathy [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Connection connection]. An array of [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel channels] pre-created in the activity room is returned, too. There is at least a text chat and a tubes channel at&lt;br /&gt;
&lt;br /&gt;
 Service:     (tp_service)&lt;br /&gt;
 Object path: (channels[i])&lt;br /&gt;
 Interface:   &#039;org.freedesktop.Telepathy.Channel&#039;&lt;br /&gt;
&lt;br /&gt;
Use GetChannelType() to tell the channels apart:&lt;br /&gt;
&lt;br /&gt;
 if (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Tubes&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
 elseif (channel.GetChannelType() == &#039;org.freedesktop.Telepathy.Channel.Type.Text&#039;)&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
===Stream Tubes===&lt;br /&gt;
A stream tube forwards a socket to a remote host (similar to ssh forwarding, but not encrypted). The activity can set up a listening socket by whatever means and then create a tube to forward it:&lt;br /&gt;
&lt;br /&gt;
 tube_id = channel.OfferStreamTube(     # sa{sv}uvuv -&amp;gt; u&lt;br /&gt;
               &#039;service-name&#039;,          # well-known TCP service name conforming to RFC 2782, see [http://www.dns-sd.org/ServiceTypes.html]&lt;br /&gt;
               {},                      # dict of params&lt;br /&gt;
               2,                       # socket type (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               (&#039;127.0.0.1&#039;, 12345),    # socket address (depends on type)&lt;br /&gt;
               0, 0)                    # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
You can forward Unix, IPv4, or IPv6 sockets. Access control is restricted to localhost by default.&lt;br /&gt;
&lt;br /&gt;
New tubes are announced by a signal:&lt;br /&gt;
&lt;br /&gt;
 NewTube ( u: tube_id, u: initiator, u: type, s: service, a{sv}: parameters, u: state )&lt;br /&gt;
&lt;br /&gt;
and you can list all available tubes:&lt;br /&gt;
&lt;br /&gt;
 tubes = channel.ListTubes()            # -&amp;gt; a(uuusa{sv}u), same as in NewTube signal&lt;br /&gt;
&lt;br /&gt;
To connect to a tube:&lt;br /&gt;
&lt;br /&gt;
 address = channel.AcceptStreamTube(   # uuuv -&amp;gt; v&lt;br /&gt;
               tube_id,&lt;br /&gt;
               2,                      # socket type to return (0=Unix, 2=IPv4, 3=IPv6)&lt;br /&gt;
               0, 0)                   # access control &amp;amp; params&lt;br /&gt;
&lt;br /&gt;
which returns an address struct of the specified type, e.g., (&#039;127.0.0.1&#039;, 45679). Then just connect a socket to that address and you are ready to share data.&lt;br /&gt;
&lt;br /&gt;
===D-Bus Tubes===&lt;br /&gt;
&#039;&#039;to be continued. In the mean time, see [[olpc:Presence Service D-Bus API]] and [http://telepathy.freedesktop.org/spec-0.16.html#org.freedesktop.Telepathy.Channel.Type.Tubes Tubes]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:API]]&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Oversight_Board/2010-2011-candidates&amp;diff=58695</id>
		<title>Oversight Board/2010-2011-candidates</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Oversight_Board/2010-2011-candidates&amp;diff=58695"/>
		<updated>2010-10-31T13:31:53Z</updated>

		<summary type="html">&lt;p&gt;Bert: Undo revision 58692 by MartinDengler (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{GoogleTrans-en}}&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Election==&lt;br /&gt;
Three (3) seats are open ([[Sugar Labs/Governance#Oversight_Board|due to staggered seat terms]]) for election / re-election to the [[Oversight Board|Sugar Labs Oversight Board]] for 2010-2011: [[User:cjb|Chris Ball]], [[User:Holt|Adam Holt]], [[User:SeanDaly|Sean Daly]]&#039;s seats.&lt;br /&gt;
&lt;br /&gt;
==Candidates==&lt;br /&gt;
Here are the candidates:&lt;br /&gt;
&lt;br /&gt;
* [http://google.com/search?q=adam+holt+mit Adam Holt] ([[User:Holt|7-point platform]], [http://lists.sugarlabs.org/archive/iaep/2010-October/011885.html look-reform-in-the-eye proposal])&lt;br /&gt;
* [[User:SMParrish|Steven Parrish]]&lt;br /&gt;
* [[User:cjb|Chris Ball]]&lt;br /&gt;
* Rosamel Norma Ramirez Mendez ([http://www.blogedu-rosamel.blogspot.com/ blog])&lt;br /&gt;
* Gerald Ardito ([http://web.me.com/geraldar/The_Shape_of_Disruption/Welcome.html/ doctoral work website])&lt;br /&gt;
* [[User:Sebastian|Sebastian Silva]]&lt;br /&gt;
* [[User:Alsroot/SLOBs_election_platform|Aleksey Lim]], [[User:Alsroot/Sugar_Architecture|&amp;quot;Sugar Architecture&amp;quot;]]&lt;br /&gt;
* [http://wiki.laptop.org/go/User:Claudia_Urrea| Claudia Urrea]&lt;br /&gt;
&lt;br /&gt;
==Candidate list is OPEN==&lt;br /&gt;
&lt;br /&gt;
PLEASE ADD YOUR NAME and a link to some background information or position statement.&lt;br /&gt;
&lt;br /&gt;
==Candidate list CLOSING deadline==&lt;br /&gt;
&lt;br /&gt;
The candidate list will be CLOSED (frozen) on November 1st 11:59PM [http://www.timeanddate.com/library/abbreviations/timezones/na/edt.html EDT], 2010)&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Oversight_Board/2009-2010-candidates]]&lt;br /&gt;
* 23 September 2009 - [http://lists.sugarlabs.org/archive/iaep/2009-September/008620.html Oversight Board election procedure update]&lt;br /&gt;
* [[Archive/Current Events/2009-08-05#Help_wanted]]&lt;br /&gt;
* [[Sugar Labs/Members]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Oversight board]]&lt;br /&gt;
[[Category:Governance]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Team]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57768</id>
		<title>0.90/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57768"/>
		<updated>2010-10-01T08:40:31Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.90/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.90 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sucrose 0.90 is the latest version of the Sugar learning environment: Sugar&#039;s focus is ease of use, stability, and first-class internationalization. Sugar is Free and Open Source Software and provides tools for learning. Furthermore, Sugar provides a flexible and powerful platform for activity developers. Sugar consists of [[Taxonomy#Glucose:_The_base_Sugar_environment|Glucose]], the base system environment; and [[Taxonomy#Fructose:_The_set_of_demonstration_activities|Fructose]], a set of demonstration activities. This new release contains many new features, performance and code improvements, bug fixes, and translations.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
=== Remove the Presence Service ===&lt;br /&gt;
Tomeu Vizoso from Collabora has been doing a great work to remove the [[Features/Remove_Presence_Service |Presence Service]]. There are no directly visible changes for the user but the overall collaboration experience should be more stable.&lt;br /&gt;
&lt;br /&gt;
=== Sugar Ad-hoc networks ===&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. The [[Features/Sugar_Adhoc_Networks| Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. Simon Schampijer from OLPC has been working on this Feature and back ported it as well to Sugar 0.84.&lt;br /&gt;
&lt;br /&gt;
=== Enhanced color selector ===&lt;br /&gt;
A new [[Features/Enhanced color selector| color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. Originally proposed for 0.88 this Feature went through several design iterations and finally consensus was reached. Now, we are excited to hear what the learners think about it.&lt;br /&gt;
&lt;br /&gt;
=== Spiral Home View ===&lt;br /&gt;
Walter Bender has been working on another Feature during this cycle. [[Features/Spiral_Home_View |The Spiral Home View]] is an enhancement to the Home View to enable the display of more icons. The idea is that after the circle becomes too large, rather than shrinking the icons, it morphs into a spiral.&lt;br /&gt;
&lt;br /&gt;
=== New ordering options in the Journal ===&lt;br /&gt;
Andrés Ambrois has been adding [[Features/Journal_Sort | new filtering options]] to the Journal. You can order now by size, creation date and modification date. The Feature originally implemented for [[Dextrose]] and sponsored by [http://activitycentral.org activity central] has been found it&#039;s way successfully into 0.90, too.&lt;br /&gt;
&lt;br /&gt;
=== New Keybindings for the Frame and Journal ===&lt;br /&gt;
Daniel Drake has been adding keybindings for the Journal (F5) and the Frame (F6). This will help to access those important views quicker on hardware where there is no designated key.&lt;br /&gt;
&lt;br /&gt;
=== Turtle Art ===&lt;br /&gt;
&lt;br /&gt;
The most visible changes are the incorporation of some new blocks, such as the &#039;Fill&#039; block for created filled polygons, Gray, Black, and White blocks, and the &#039;Turtle Sees&#039; block, that enables the turtle to directly interact with its canvas. There is also a [http://turtleartsite.appspot.com/ new site] for uploading and downloading Turtle Art projects.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:TAMaze.png|Turtle &#039;sees&#039;&lt;br /&gt;
File:Turtle Art Site.png|http://turtleartsite.appspot.com/&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please see [[0.90/TurtleArt]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Etoys ===&lt;br /&gt;
Sugar 0.90 includes the latest Etoys release. Some of the new features in Etoys 4.1 are DrGeo, speech bubbles, a timer tile and persistent preferences. Also, the QuickGuides have been translated into several languages.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Etoys41-DrGeo.png|DrGeo in Etoys&lt;br /&gt;
File:Etoys41-Bubble.png|Speech Bubbles&lt;br /&gt;
File:Etoys41-Guide.png|Translated QuickGuide &lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
An important change is that projects are not saved automatically anymore when you exit the Etoys activity. Instead of the regular Stop button, you will see an Exit button:&lt;br /&gt;
&lt;br /&gt;
[[File:Etoys41-Exit.png‎]]&lt;br /&gt;
&lt;br /&gt;
Find out more in the [http://squeakland.org/download/releaseNotes.jsp Etoys 4.1 release notes].&lt;br /&gt;
&lt;br /&gt;
=== Sugar Activities ===&lt;br /&gt;
&lt;br /&gt;
While we bundle a small subset of the Sugar Activities within Sucrose, most of the Activity &amp;quot;activity&amp;quot; can be tracked by visiting [http://activities.sugarlabs.org the Sugar Activity Library]. &lt;br /&gt;
&lt;br /&gt;
We have recently surpassed &#039;&#039;3.6-million&#039;&#039; Sugar Activity downloads! There are &#039;&#039;hundreds of activities&#039;&#039; available for download in a variety of categories! &lt;br /&gt;
&lt;br /&gt;
Thanks to &#039;&#039;&#039;&#039;&#039;all&#039;&#039;&#039; the activity maintainers and developers&#039;&#039; for making this happen.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Category !! No. of Activities&lt;br /&gt;
|-&lt;br /&gt;
|Search &amp;amp;amp; discovery||36&lt;br /&gt;
|-&lt;br /&gt;
|Documents||13&lt;br /&gt;
|-&lt;br /&gt;
|News||3&lt;br /&gt;
|-&lt;br /&gt;
|Chat, mail and talk||6&lt;br /&gt;
|-&lt;br /&gt;
|Media creation||25&lt;br /&gt;
|-&lt;br /&gt;
|Programming||13&lt;br /&gt;
|-&lt;br /&gt;
|Maths &amp;amp;amp; science||85&lt;br /&gt;
|-&lt;br /&gt;
|Maps &amp;amp;amp; geography||5&lt;br /&gt;
|-&lt;br /&gt;
|Media players||1&lt;br /&gt;
|-&lt;br /&gt;
|Games||60&lt;br /&gt;
|-&lt;br /&gt;
|Teacher tools||107&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Recent additions ====&lt;br /&gt;
[http://activities.sugarlabs.org/en-US/sugar/browse/type:1/cat:all?sort=newest Recent additions] include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:DrGeo.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]&lt;br /&gt;
File:Pukallanapac.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]&lt;br /&gt;
File:ConstellationsFlashCards.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]&lt;br /&gt;
File:Gtranslator.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]&lt;br /&gt;
File:Words.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]&lt;br /&gt;
File:VNClauncher.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]&lt;br /&gt;
File:SunMoonMusicMC.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]&lt;br /&gt;
File:GetBooks.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]&lt;br /&gt;
File:StarChart.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]&lt;br /&gt;
File:XaoS.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]&lt;br /&gt;
File:TurtleArtMini.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]&lt;br /&gt;
File:SuperTux.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]&lt;br /&gt;
File:Nepohualtzintzin.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]&lt;br /&gt;
File:SlideruleA.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Activity !! Description&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]||Dr. Geo is an interactive geometry activity. Dr. Geo allows one to create geometric figure plus the interactive manipulation of such figure in respect with their geometric constraints. It is usable in teaching situation with students from primary or secondary level. It is simple and effective with some unique features as scripting and Smalltalk programming. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]||A puzzle: Move the pieces until the circles are all solid circles. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]||This program teaches the constellations by means of a flash-card-like interface. The program draws a constellation and the student has to pick the correct name from a list of five possible choices. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]||A Sugarized version of the translation file editor &amp;quot;Gtranslator&amp;quot; The GTranslator activity allows to translate the po files locally. This should allow users without a permanent Internet access to translate off-line the localization files downloaded from the Pootle translation server and to contribute to the localization of Sugar to their own language. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]||A multi-lingual dictionary with speech synthesis. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]||This activity helps you broadcast your screen to another computer. It will automatically launch a VNC server (X11vnc) and display your IP address. You can then connect and view the screen of Sugar on another conmputer using any VNC client (e.g. TigerVNC, UltraVNC Viewer, RealVNC, etc).&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]||Sun-Moon Music MC - Realtime Sonic Environments for Children, Multiple MIDI Controller version. Collaborative exploration and performance encouraged. Requires 1 or more MIDI controllers.  This version of Sun-Moon Music is especially designed for collaborative exploration and performance. All MIDI control devices must be set to the same channel.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]||The Get Books activity lets users search and retrieve books from a variety of sources (Internet Archive, Feedbooks, etc). It supports the OPDS protocol for book discovery.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]||This activity will display a map of the sky showing the position of the visible stars, some of the larger and brighter deep-sky objects (DSOs), the &amp;quot;classical&amp;quot; planets, the sun and the moon. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]||XaoS is an interactive fractal zoomer. It allows the user to continuously to zoom in or out of a fractal in a fluid, continuous motion. This capability makes XaoS great for exploring fractals, and it’s just plain fun! &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]||Turtle Art Mini is a simple graphical programming environment. It is modeled on the Logo programming language and it emphasized graphical expression by learners new to programming. (Turtle Art Mimi is a subset of the [http://activities.sugarlabs.org/en-US/sugar/addon/4027 Turtle Art] activity – AKA Turtle Blocks)&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]||A Sugar clone of the Super Tux game.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]||Abacus is a simple, customizable abacus activity for Sugar. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]||Sliderule is a simple, customizable slide rule activity for Sugar. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== New experimental activities ====&lt;br /&gt;
These are activities under development that may be of interest to Sugar users:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:ProducePuzzle.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4322 Produce Puzzle (experimental)]&lt;br /&gt;
File:Lemonade.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4321 Lemonade (experimental)]&lt;br /&gt;
File:GComprisAdministration.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4314 GCompris Administration (experimental)]&lt;br /&gt;
File:TVRadio.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4310 TV and Radio (experimental)]&lt;br /&gt;
File:FreeFromMalaria.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4309 FreeFromMalaria (experimental)]&lt;br /&gt;
File:OpenVideoChat.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4305 Open Video Chat (experimental)]&lt;br /&gt;
File:MathGraph32.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4303 MathGraph32 (experimental)]&lt;br /&gt;
File:SonataMediaPlayer.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4301 Sonata Media Player (experimental)]&lt;br /&gt;
File:Wine.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4296 Wine (experimental)]&lt;br /&gt;
File:TetrisMat-icon.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4292 TetrisMat (experimental)]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is new for distributors and deployers ==&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.90 developer platform.&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
Add ErrorAlert inherited from Alert.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
Print warnings about the deprecated activity.info fields.&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
There are still many activities that do not use the new activity toolbars introduced in 0.86. We encourage the switch to use the new toolbars as there have been huge improvements in usability (e.g. stopping an activity).&lt;br /&gt;
&lt;br /&gt;
Jim Simmons has written a guide to writing Sugar Activities (Please see [http://en.flossmanuals.net/ActivitiesGuideSugar/Introduction Make your own Sugar Activities!]) which details how to convert your activity to the new toolbars without compromising performance on old Sugar systems.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There a no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package sugar for your favorite distribution or just want to examine sugar&#039;s lovely code ;) you can find all the source code of each module at the links below. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.90.1.tar.bz2 sugar 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.90.0.tar.bz2 sugar-datastore 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.90.0.tar.bz2 sugar-toolkit 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.1.tar.bz2 sugar-base 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.1.tar.bz2 sugar-presence-service 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.90.0.tar.bz2 sugar-artwork 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2388.tar.gz etoys 4.1.2388]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-118.tar.bz2 Browse 118]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-34.tar.bz2 Calculate 34]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-68.tar.bz2 Chat 68]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-98.tar.bz2 TurtleArt 98]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-20.tar.bz2 Jukebox 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-24.tar.bz2 Log 24]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-15.tar.bz2 ImageViewer 15]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-71.tar.bz2 Write 71]&lt;br /&gt;
&lt;br /&gt;
== Looking at the release cycle details ==&lt;br /&gt;
You can browse the notes of each development release in [[{{Upcoming Stable Release}}]]. Their respective sources are listed there as well. &lt;br /&gt;
&lt;br /&gt;
== Looking Forward to 0.92 ==&lt;br /&gt;
Introspection!&lt;br /&gt;
&lt;br /&gt;
Planning of the next release cycle has started at [[0.92/Roadmap]].&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that review patches and make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing during the development cycle a Sugar version to test with,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57767</id>
		<title>0.90/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57767"/>
		<updated>2010-10-01T08:35:23Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.90/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.90 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sucrose 0.90 is the latest version of the Sugar learning environment: Sugar&#039;s focus is ease of use, stability, and first-class internationalization. Sugar is Free and Open Source Software and provides tools for learning. Furthermore, Sugar provides a flexible and powerful platform for activity developers. Sugar consists of [[Taxonomy#Glucose:_The_base_Sugar_environment|Glucose]], the base system environment; and [[Taxonomy#Fructose:_The_set_of_demonstration_activities|Fructose]], a set of demonstration activities. This new release contains many new features, performance and code improvements, bug fixes, and translations.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
=== Remove the Presence Service ===&lt;br /&gt;
Tomeu Vizoso from Collabora has been doing a great work to remove the [[Features/Remove_Presence_Service |Presence Service]]. There are no directly visible changes for the user but the overall collaboration experience should be more stable.&lt;br /&gt;
&lt;br /&gt;
=== Sugar Ad-hoc networks ===&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. The [[Features/Sugar_Adhoc_Networks| Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. Simon Schampijer from OLPC has been working on this Feature and back ported it as well to Sugar 0.84.&lt;br /&gt;
&lt;br /&gt;
=== Enhanced color selector ===&lt;br /&gt;
A new [[Features/Enhanced color selector| color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. Originally proposed for 0.88 this Feature went through several design iterations and finally consensus was reached. Now, we are excited to hear what the learners think about it.&lt;br /&gt;
&lt;br /&gt;
=== Spiral Home View ===&lt;br /&gt;
Walter Bender has been working on another Feature during this cycle. [[Features/Spiral_Home_View |The Spiral Home View]] is an enhancement to the Home View to enable the display of more icons. The idea is that after the circle becomes too large, rather than shrinking the icons, it morphs into a spiral.&lt;br /&gt;
&lt;br /&gt;
=== New ordering options in the Journal ===&lt;br /&gt;
Andrés Ambrois has been adding [[Features/Journal_Sort | new filtering options]] to the Journal. You can order now by size, creation date and modification date. The Feature originally implemented for [[Dextrose]] and sponsored by [http://activitycentral.org activity central] has been found it&#039;s way successfully into 0.90, too.&lt;br /&gt;
&lt;br /&gt;
=== New Keybindings for the Frame and Journal ===&lt;br /&gt;
Daniel Drake has been adding keybindings for the Journal (F5) and the Frame (F6). This will help to access those important views quicker on hardware where there is no designated key.&lt;br /&gt;
&lt;br /&gt;
=== Turtle Art ===&lt;br /&gt;
&lt;br /&gt;
The most visible changes are the incorporation of some new blocks, such as the &#039;Fill&#039; block for created filled polygons, Gray, Black, and White blocks, and the &#039;Turtle Sees&#039; block, that enables the turtle to directly interact with its canvas. There is also a [http://turtleartsite.appspot.com/ new site] for uploading and downloading Turtle Art projects.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:TAMaze.png|Turtle &#039;sees&#039;&lt;br /&gt;
File:Turtle Art Site.png|http://turtleartsite.appspot.com/&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please see [[0.90/TurtleArt]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Etoys ===&lt;br /&gt;
Sugar 0.90 includes the latest Etoys release. Some of the new features in Etoys 4.1 are DrGeo, speech bubbles, a timer tile and settable preferences. Also, the QuickGuides have been translated into several languages.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Etoys41-DrGeo.png|DrGeo in Etoys&lt;br /&gt;
File:Etoys41-Bubble.png|Speech Bubbles&lt;br /&gt;
File:Etoys41-Guide.png|Translated QuickGuide &lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
An important change is that projects are not saved automatically anymore when you exit the activity. Instead of the regular Stop button, you will see an Exit button:&lt;br /&gt;
&lt;br /&gt;
[[File:Etoys41-Exit.png‎]]&lt;br /&gt;
&lt;br /&gt;
Find out more in the [http://squeakland.org/download/releaseNotes.jsp 4.1 release notes].&lt;br /&gt;
&lt;br /&gt;
=== Sugar Activities ===&lt;br /&gt;
&lt;br /&gt;
While we bundle a small subset of the Sugar Activities within Sucrose, most of the Activity &amp;quot;activity&amp;quot; can be tracked by visiting [http://activities.sugarlabs.org the Sugar Activity Library]. &lt;br /&gt;
&lt;br /&gt;
We have recently surpassed &#039;&#039;3.6-million&#039;&#039; Sugar Activity downloads! There are &#039;&#039;hundreds of activities&#039;&#039; available for download in a variety of categories! &lt;br /&gt;
&lt;br /&gt;
Thanks to &#039;&#039;&#039;&#039;&#039;all&#039;&#039;&#039; the activity maintainers and developers&#039;&#039; for making this happen.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Category !! No. of Activities&lt;br /&gt;
|-&lt;br /&gt;
|Search &amp;amp;amp; discovery||36&lt;br /&gt;
|-&lt;br /&gt;
|Documents||13&lt;br /&gt;
|-&lt;br /&gt;
|News||3&lt;br /&gt;
|-&lt;br /&gt;
|Chat, mail and talk||6&lt;br /&gt;
|-&lt;br /&gt;
|Media creation||25&lt;br /&gt;
|-&lt;br /&gt;
|Programming||13&lt;br /&gt;
|-&lt;br /&gt;
|Maths &amp;amp;amp; science||85&lt;br /&gt;
|-&lt;br /&gt;
|Maps &amp;amp;amp; geography||5&lt;br /&gt;
|-&lt;br /&gt;
|Media players||1&lt;br /&gt;
|-&lt;br /&gt;
|Games||60&lt;br /&gt;
|-&lt;br /&gt;
|Teacher tools||107&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Recent additions ====&lt;br /&gt;
[http://activities.sugarlabs.org/en-US/sugar/browse/type:1/cat:all?sort=newest Recent additions] include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:DrGeo.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]&lt;br /&gt;
File:Pukallanapac.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]&lt;br /&gt;
File:ConstellationsFlashCards.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]&lt;br /&gt;
File:Gtranslator.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]&lt;br /&gt;
File:Words.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]&lt;br /&gt;
File:VNClauncher.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]&lt;br /&gt;
File:SunMoonMusicMC.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]&lt;br /&gt;
File:GetBooks.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]&lt;br /&gt;
File:StarChart.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]&lt;br /&gt;
File:XaoS.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]&lt;br /&gt;
File:TurtleArtMini.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]&lt;br /&gt;
File:SuperTux.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]&lt;br /&gt;
File:Nepohualtzintzin.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]&lt;br /&gt;
File:SlideruleA.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Activity !! Description&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]||Dr. Geo is an interactive geometry activity. Dr. Geo allows one to create geometric figure plus the interactive manipulation of such figure in respect with their geometric constraints. It is usable in teaching situation with students from primary or secondary level. It is simple and effective with some unique features as scripting and Smalltalk programming. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]||A puzzle: Move the pieces until the circles are all solid circles. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]||This program teaches the constellations by means of a flash-card-like interface. The program draws a constellation and the student has to pick the correct name from a list of five possible choices. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]||A Sugarized version of the translation file editor &amp;quot;Gtranslator&amp;quot; The GTranslator activity allows to translate the po files locally. This should allow users without a permanent Internet access to translate off-line the localization files downloaded from the Pootle translation server and to contribute to the localization of Sugar to their own language. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]||A multi-lingual dictionary with speech synthesis. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]||This activity helps you broadcast your screen to another computer. It will automatically launch a VNC server (X11vnc) and display your IP address. You can then connect and view the screen of Sugar on another conmputer using any VNC client (e.g. TigerVNC, UltraVNC Viewer, RealVNC, etc).&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]||Sun-Moon Music MC - Realtime Sonic Environments for Children, Multiple MIDI Controller version. Collaborative exploration and performance encouraged. Requires 1 or more MIDI controllers.  This version of Sun-Moon Music is especially designed for collaborative exploration and performance. All MIDI control devices must be set to the same channel.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]||The Get Books activity lets users search and retrieve books from a variety of sources (Internet Archive, Feedbooks, etc). It supports the OPDS protocol for book discovery.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]||This activity will display a map of the sky showing the position of the visible stars, some of the larger and brighter deep-sky objects (DSOs), the &amp;quot;classical&amp;quot; planets, the sun and the moon. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]||XaoS is an interactive fractal zoomer. It allows the user to continuously to zoom in or out of a fractal in a fluid, continuous motion. This capability makes XaoS great for exploring fractals, and it’s just plain fun! &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]||Turtle Art Mini is a simple graphical programming environment. It is modeled on the Logo programming language and it emphasized graphical expression by learners new to programming. (Turtle Art Mimi is a subset of the [http://activities.sugarlabs.org/en-US/sugar/addon/4027 Turtle Art] activity – AKA Turtle Blocks)&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]||A Sugar clone of the Super Tux game.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]||Abacus is a simple, customizable abacus activity for Sugar. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]||Sliderule is a simple, customizable slide rule activity for Sugar. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== New experimental activities ====&lt;br /&gt;
These are activities under development that may be of interest to Sugar users:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:ProducePuzzle.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4322 Produce Puzzle (experimental)]&lt;br /&gt;
File:Lemonade.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4321 Lemonade (experimental)]&lt;br /&gt;
File:GComprisAdministration.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4314 GCompris Administration (experimental)]&lt;br /&gt;
File:TVRadio.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4310 TV and Radio (experimental)]&lt;br /&gt;
File:FreeFromMalaria.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4309 FreeFromMalaria (experimental)]&lt;br /&gt;
File:OpenVideoChat.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4305 Open Video Chat (experimental)]&lt;br /&gt;
File:MathGraph32.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4303 MathGraph32 (experimental)]&lt;br /&gt;
File:SonataMediaPlayer.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4301 Sonata Media Player (experimental)]&lt;br /&gt;
File:Wine.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4296 Wine (experimental)]&lt;br /&gt;
File:TetrisMat-icon.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4292 TetrisMat (experimental)]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is new for distributors and deployers ==&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.90 developer platform.&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
Add ErrorAlert inherited from Alert.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
Print warnings about the deprecated activity.info fields.&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
There are still many activities that do not use the new activity toolbars introduced in 0.86. We encourage the switch to use the new toolbars as there have been huge improvements in usability (e.g. stopping an activity).&lt;br /&gt;
&lt;br /&gt;
Jim Simmons has written a guide to writing Sugar Activities (Please see [http://en.flossmanuals.net/ActivitiesGuideSugar/Introduction Make your own Sugar Activities!]) which details how to convert your activity to the new toolbars without compromising performance on old Sugar systems.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There a no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package sugar for your favorite distribution or just want to examine sugar&#039;s lovely code ;) you can find all the source code of each module at the links below. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.90.1.tar.bz2 sugar 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.90.0.tar.bz2 sugar-datastore 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.90.0.tar.bz2 sugar-toolkit 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.1.tar.bz2 sugar-base 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.1.tar.bz2 sugar-presence-service 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.90.0.tar.bz2 sugar-artwork 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2388.tar.gz etoys 4.1.2388]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-118.tar.bz2 Browse 118]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-34.tar.bz2 Calculate 34]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-68.tar.bz2 Chat 68]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-98.tar.bz2 TurtleArt 98]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-20.tar.bz2 Jukebox 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-24.tar.bz2 Log 24]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-15.tar.bz2 ImageViewer 15]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-71.tar.bz2 Write 71]&lt;br /&gt;
&lt;br /&gt;
== Looking at the release cycle details ==&lt;br /&gt;
You can browse the notes of each development release in [[{{Upcoming Stable Release}}]]. Their respective sources are listed there as well. &lt;br /&gt;
&lt;br /&gt;
== Looking Forward to 0.92 ==&lt;br /&gt;
Introspection!&lt;br /&gt;
&lt;br /&gt;
Planning of the next release cycle has started at [[0.92/Roadmap]].&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that review patches and make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing during the development cycle a Sugar version to test with,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Exit.png&amp;diff=57766</id>
		<title>File:Etoys41-Exit.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Exit.png&amp;diff=57766"/>
		<updated>2010-10-01T08:33:47Z</updated>

		<summary type="html">&lt;p&gt;Bert: Exit button instead of Stop button in Etoys 4.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Exit button instead of Stop button in Etoys 4.1&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=The_Undiscoverable&amp;diff=57765</id>
		<title>The Undiscoverable</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=The_Undiscoverable&amp;diff=57765"/>
		<updated>2010-10-01T08:23:32Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{TOCright}}&lt;br /&gt;
[[Category:Help]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some ideas are not easy to discover; the concept of guided [[discovery]], where a mentor helps point a learner in a fruitful direction, can accelerate the pace of learning. Some Sugar features are not easy to discover and while we are working to improve upon this, we provide some guides to discovery below.&lt;br /&gt;
&lt;br /&gt;
Eventually, as editors have sufficient material, the official documentation at &lt;br /&gt;
[http://www.flossmanuals.net/ FLOSS Manuals] should be updated. (It&#039;s a wiki, too.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;New project&#039;&#039;&#039;: [http://www.booki.cc/discovering-discovery/ Discovering Discovery] in the FLOSS Manuals Booki software.--[[User:Mokurai|Mokurai]] 11:44, 29 September 2010 (EDT)&lt;br /&gt;
 &lt;br /&gt;
No matter how well we do in making Sugar discoverable, there are necessarily some things that even a born lever-puller and button-clicker will not find easily, or will not understand fully. This page contains a list of such things, ranging from the almost but not quite obvious to the entirely opaque. We can consider whether some of these can be improved, but we know that there is a limit. So we have to alert teachers to these issues, and assist them to alert the children.&lt;br /&gt;
&lt;br /&gt;
Nothing is 100% discoverable or 100% undiscoverable. There are many features of Sugar that can be discovered, without their use cases being in any way obvious. The question, then, is how to provide discovery projects where we know that a particular usage is appropriate, and include a hint on the feature in the lesson plan. In other cases, the children understand immediately what a function is for, as soon as they know it exists. In those cases, you generally don&#039;t have to show them twice.&lt;br /&gt;
&lt;br /&gt;
Many things that would not be discovered by one individual before getting frustrated will be rapidly discovered by one child in the group and shared before any of the group get frustrated. In teaching science, Alan Kay calls this a &amp;quot;Galileo moment&amp;quot;. Is this an an adequate standard of discoverability for software, or should features be discoverable by a child in isolation? Where they are not, we want teachers to know that, and we want to plan accordingly.&lt;br /&gt;
&lt;br /&gt;
Many of the Activities would benefit from a Help feature.&lt;br /&gt;
&lt;br /&gt;
We should probably create a subpage for each of these issues, or point to an existing Wiki page that has the information.&lt;br /&gt;
&lt;br /&gt;
Again, all of these items should be clearly documented and even specially called out in the [http://www.flossmanuals.net/ FLOSS Manuals] Sugar and XO documents.&lt;br /&gt;
&lt;br /&gt;
==Sugar UI==&lt;br /&gt;
&lt;br /&gt;
* Views: Neighborhood, Friends, Home, current Activity&lt;br /&gt;
&lt;br /&gt;
* Wireless mesh channels and access points&lt;br /&gt;
&lt;br /&gt;
==Icon colors and user names==&lt;br /&gt;
:Personalized icons? Drawings? Pictures? How can kids make their own icon? It&#039;s a surprisingly big thing to est. an iconic identity for many... just look at forums where kids(and adults!) hang out.--[[User:Dennis Daniels|Dennis Daniels]] 16:13, 4 August 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Search wireless connections and people by name==&lt;br /&gt;
Easier to find your friend if  you recognize their icon. --[[User:Dennis Daniels|Dennis Daniels]] 16:15, 4 August 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Right-click/hover menus==&lt;br /&gt;
Point to an icon and wait a second for its name to appear. Wait a bit longer for the accompanying menu to appear. Or, without having to wait, just right-click (o-button on an XO) to see the name and menu.&lt;br /&gt;
::Nice if view source was there too. --[[User:Dennis Daniels|Dennis Daniels]] 16:15, 4 August 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Activities==&lt;br /&gt;
In home view (hotkey F3), there are buttons to switch between the view of favorites in a ring and a list of all installed Activities. Select the star by an Activity to make it a Favorite. The hover menu for a Favorite includes the option to remove it from favorites without deleting it, and also an Erase option which deletes that activity! &lt;br /&gt;
::For a school admin trying to keep machines uniform for the next wave of kids to descend upon the computer lab the erase key can pose problems, right? --[[User:Dennis Daniels|Dennis Daniels]] 16:08, 4 August 2009 (UTC)&lt;br /&gt;
* Frame: Views and Activities on top; Friends on the right; hardware on the bottom; open documents on the left.&lt;br /&gt;
&lt;br /&gt;
* [[The Undiscoverable/Collaboration|Collaboration]]&lt;br /&gt;
&lt;br /&gt;
* Use of Keep button: Keep places a checkpoint of the current state of your application in the Journal, including a screen shot, Activity state, and metadata. The user can rename the session from the name of the Activity to something specific to the session, and add a description and tags. Users do not agree on why and when to use Keep.&lt;br /&gt;
&lt;br /&gt;
===Screen capture===&lt;br /&gt;
An important use case for the Keep button. How do we store just the image, without the software state? Some Activities, including Turtle Art, have a button for this purpose. &lt;br /&gt;
*: &amp;lt;Alt&amp;gt; + 1 captures the screen and stores a screenshot in the Journal. &lt;br /&gt;
&lt;br /&gt;
===View source?===&lt;br /&gt;
Not fully implemented. On the menu in several applications.&lt;br /&gt;
&lt;br /&gt;
:What&#039;s the hotkey to view source? Is there a hotkey to view the log for that specific acitivity?--[[User:Dennis Daniels|Dennis Daniels]] 16:10, 4 August 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
* Copy and paste between activities? (Sometimes)&lt;br /&gt;
&lt;br /&gt;
===How to quit an activity===&lt;br /&gt;
&#039;&#039;Most&#039;&#039; activities have a &amp;quot;stop-sign&amp;quot; icon under the Activity Tab on the toolbar at the top of the screen. (GCompris activities have a &amp;quot;exit-door&amp;quot; icon in the toolbar on the bottom of the screen. Some other activities may have a quit menu item.) &#039;&#039;Every&#039;&#039; activity has Stop in the hover menu associated with the Activity icon in the Frame.&lt;br /&gt;
&lt;br /&gt;
::Not all activities respond to the &#039;stop-sign&#039; especially when there are system/activity crashes caused by bugs. How do users and teachers(!) kill _that_ activity?--[[User:Dennis Daniels|Dennis Daniels]] 16:09, 4 August 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
* Start an Activity without resuming last session: Select Start from hover menu.&lt;br /&gt;
&lt;br /&gt;
===Sugar-Emulator Screen Size Adjustment===&lt;br /&gt;
* In Terminal:&lt;br /&gt;
*: {{Code|sugar-emulator -i 600x500}} (fits the screen for a 10&amp;quot; Netbook as a window)&lt;br /&gt;
*: {{Code|sugar-emulator -f}} (Full Screen) &lt;br /&gt;
* Help for sugar-emulator&lt;br /&gt;
*: {{Code|sugar-emulator --help}}&lt;br /&gt;
&lt;br /&gt;
* Modify the menu item Applications-&amp;gt;Education-&amp;gt;Sugar&lt;br /&gt;
*: Use &#039;Main Menu&#039; utility (alacarte) or edit a separate launcher&lt;br /&gt;
*# [right click]-&amp;gt;[add launcher to desktop]&lt;br /&gt;
*# right click on icon on desktop&lt;br /&gt;
*# Properties, Command:/usr/bin/sugar-emulator &#039;&#039;&#039;-i 832x624&#039;&#039;&#039;&lt;br /&gt;
*# Close&lt;br /&gt;
&lt;br /&gt;
* Now a smaller Xephyr window will launch&lt;br /&gt;
** 832x624 matches the XO display proportions (Pages in Browse will mimic the layout of those on an XO.)&lt;br /&gt;
&lt;br /&gt;
===Localization===&lt;br /&gt;
* [[The Undiscoverable/Change keyboard|Change keyboard]]&lt;br /&gt;
&lt;br /&gt;
* [[The Undiscoverable/Change UI language|Change UI language]]&lt;br /&gt;
&lt;br /&gt;
* [[The Undiscoverable/Fonts|Fonts]]&lt;br /&gt;
&lt;br /&gt;
=== Remote collaboration ===&lt;br /&gt;
Using Community Jabber servers (Listings and how to change):&lt;br /&gt;
* [OLPC:Community_Jabber_Servers OLPC Community Jabber servers]&lt;br /&gt;
&lt;br /&gt;
* [[Community Jabber servers|local display of the OLPC Community Jabber servers]]&lt;br /&gt;
* see Terminal listing below for how to change&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
&lt;br /&gt;
Although there is no such thing as an intuitive icon, it is sometimes possible to use icons that relate to experience, and it is generally possible to make icons mnemonic, so that they don&#039;t have to be explained more than once. Note that the common icon for saving a file in GUIS for Linux, Mac, and Windows is the obsolete floppy disk. A billion people have learned it, so it has become almost unchangeable. We have started over in Sugar.&lt;br /&gt;
&lt;br /&gt;
* File types. &lt;br /&gt;
* InfoSlicer&lt;br /&gt;
&lt;br /&gt;
==Journal==&lt;br /&gt;
&lt;br /&gt;
* The default text in each entry is the name of the Activity used to create it, or the name of a downloaded file. Users can edit this text to provide a meaningful title. The Description does not display in the main Journal view. Renamed sessions saved in the Journal show up on the right-click/hover menu for that Activity&#039;s icon in the Home view.&lt;br /&gt;
&lt;br /&gt;
* Tags: Poor man&#039;s database. You can tag by topic, by project, or whatever else meets your needs.&lt;br /&gt;
&lt;br /&gt;
* Searches examine the unnamed Title field, the Description, and the Tags texts. You don&#039;t have to examine entries one at a time to look for particular tags.&lt;br /&gt;
&lt;br /&gt;
* Resume session: Left-click a Journal entry to start where you left off the last time. Right-click to get the list of Activities that can open this file. Save in Record, open in Paint, for example.&lt;br /&gt;
&lt;br /&gt;
* Install Activities: Cannot install .xo over yum package. Delete Activity from /usr/share/sugar/activities, then download .xo from [http://activities.sugarlabs.org Activities repository]. Where is the result installed?&lt;br /&gt;
&lt;br /&gt;
* Copy to and from USB stick: Drag Journal entries to USB icon.&lt;br /&gt;
&lt;br /&gt;
* Copy file to Journal entry. With the appropriate file name and MIME type: &lt;br /&gt;
 copy-to-journal tamyblock.py -m text/x-python&lt;br /&gt;
&lt;br /&gt;
* When you download an image, it doesn&#039;t have a preview. Open it and close it immediately to generate one. [http://dev.sugarlabs.org/ticket/1106 Ticket #1106]&lt;br /&gt;
===Saving Work===&lt;br /&gt;
&lt;br /&gt;
Basically, we need a Save as... functionality, not just a Save that overwrites the previous version and a clumsy Save on Exit where you have to go roundabout to start up again. All of this should be bugged as a Feature Request.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;On Thu, Oct 8, 2009 at 6:42 PM, Caroline Meeks &amp;lt;caroline@solutiongrove.com&amp;gt; wrote:&lt;br /&gt;
&amp;gt; Today we worked with two groups on multiplication. They made squares with&lt;br /&gt;
&amp;gt; each side being a different multiplication problem that had the same answer.&lt;br /&gt;
&amp;gt; http://screencast.com/t/sUbiof2H&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; We also had them reflect in their Journals about what they did. &lt;br /&gt;
&amp;gt; All of this went well.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; What was horrible was trying to get the right point in the project saved to&lt;br /&gt;
&amp;gt; the Journal and then navigating to the correct place to write.&lt;br /&gt;
&amp;gt; The solution I suggest is when you click the Keep button (Journal Icon) from&lt;br /&gt;
&amp;gt; an activity that the Journal reflection dialog box appears.&lt;br /&gt;
&amp;gt; Here are the problems we had.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Hard to get to the Journal, no easy F# short cut.&lt;br /&gt;
&amp;gt; Hard to find the little arrow that gets you to where you can write.&lt;br /&gt;
&amp;gt; Especially since if the Frame is active, which it has to be to get to the&lt;br /&gt;
&amp;gt; Journal, the little bitty arrow you need to click is covered.&lt;br /&gt;
&amp;gt; When students did their assigned task they were eager to go back to&lt;br /&gt;
&amp;gt; exploring with Sugar and wrote over their work without it being saved, or&lt;br /&gt;
&amp;gt; using the same name as the assigned activity.  This was probably the worst&lt;br /&gt;
&amp;gt; outcome because then it was like they hadn&#039;t done the assignment, they had&lt;br /&gt;
&amp;gt; nothing to show for their work and we&#039;ll want to use it later for a&lt;br /&gt;
&amp;gt; portfolio.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; clicking the Activity Tab to write down the name is a PITA (this one is&lt;br /&gt;
&amp;gt; fixed in .88 I think).&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; After they reflected they wanted to immediately go back to exploring in TA&lt;br /&gt;
&amp;gt; and we had to stop them, make them change the name again. They were very&lt;br /&gt;
&amp;gt; perplexed by this because they didn&#039;t know what to name their new file&lt;br /&gt;
&amp;gt; because they hadn&#039;t done anything yet.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; The word &amp;quot;Description&amp;quot; is not very friendly. I like &amp;quot;What did you do?&amp;quot;&lt;br /&gt;
&amp;gt; Walter wants to expand it even further, I&#039;m not sure about that, its pretty&lt;br /&gt;
&amp;gt; challenging for the students to type so I&#039;m not sure we want more boxes.&lt;br /&gt;
&amp;gt; Confusion between the Keep button and the samples and the snapshot icons.&lt;br /&gt;
&amp;gt; No feedback when you click Keep so there is a tendency to click it&lt;br /&gt;
&amp;gt; repeatedly.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Activities==&lt;br /&gt;
&lt;br /&gt;
* What version of this activity am I running? The list view in Home gives the number.&lt;br /&gt;
* Add and Remove Favorites. WARNING: Erase is &#039;&#039;&#039;not&#039;&#039;&#039; Remove Favorite.&lt;br /&gt;
&lt;br /&gt;
===[http://wiki.laptop.org/go/Xo-get xo-get]===&lt;br /&gt;
&lt;br /&gt;
The obsolete xo-get script and Activity accessed a repository of Activities for installation and updates. Use [http://Activities.sugarlabs.org/ Activities.sugarlabs.org] instead.&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.laptop.org/go/Xo-get#Installation_of_xo-get Script] [http://xo-get.olpc.at/xo-get.py Download] &lt;br /&gt;
* [http://wiki.laptop.org/go/Xo-get#Installation_of_xo-get_GUI Activity]&lt;br /&gt;
&lt;br /&gt;
===Terminal===&lt;br /&gt;
&lt;br /&gt;
* XO laptop keyboard sends screen the &amp;quot;erase&amp;quot; key as the ascii code NULL (back erases) and sees &amp;quot;fn+erase&amp;quot; as code DEL (forward erase)&lt;br /&gt;
* The entire [[The undiscoverable/Command line|command line]] repertoire plus scripting&lt;br /&gt;
* Documentation: man, info, apropos&lt;br /&gt;
* Linux file system: /, ., .., cd, pwd, mkdir, rmdir, cat, touch, rm, mount, umount, /etc/fstab&lt;br /&gt;
* Standard IO: &amp;gt;, &amp;gt;&amp;gt;, &amp;lt;, |&lt;br /&gt;
* Users and groups: root, /home, su, sudo, /etc/sudoers, sudoedit, visudo, chown&lt;br /&gt;
* Permissions: chmod drwxrwxrwx ugoa&lt;br /&gt;
* Regular expressions: [0-9][a-zA-Z]?, grep&lt;br /&gt;
* File globbing: *&lt;br /&gt;
* Editors: vi, pico. The emacs editor is not installed by default.&lt;br /&gt;
* copy-from-journal copy-to-journal: Journal entries are in ~/.sugar/default/datastore. Each entry has a metadata subdirectory.&lt;br /&gt;
* sugar-control-panel command: (aboutme/network/datetime/aboutcomputer/Frame/power/language) settings. Use this command (small L) to list available functions.&lt;br /&gt;
 sugar-control-panel -l &lt;br /&gt;
* File browser: Install Midnight Commander (mc)&lt;br /&gt;
&lt;br /&gt;
See FLOSS Manuals [http://en.flossmanuals.net/terminal Terminal] and [http://en.flossmanuals.net/CommandLineIntro/AboutThisManual Introduction to the GNU/Linux Command Line] for a gentle introduction to these functions and features.&lt;br /&gt;
&lt;br /&gt;
===Etoys===&lt;br /&gt;
&lt;br /&gt;
* It&#039;s a programming language.&lt;br /&gt;
* It&#039;s huge.&lt;br /&gt;
* The tutorials are excellent as far as they go, but they stop short.&lt;br /&gt;
* [[The undiscoverable/Projects|Projects]]? What are projects? How do I do that?&lt;br /&gt;
* Program tiles&lt;br /&gt;
* Make tile&lt;br /&gt;
* Objects&lt;br /&gt;
* Code viewer&lt;br /&gt;
* Multimedia&lt;br /&gt;
* Presentations&lt;br /&gt;
* Link: http://squeakland.org/&lt;br /&gt;
* Hint: to share an Object or the desktop in e-toys&lt;br /&gt;
:Drag over a buddy it should highlight&lt;br /&gt;
&lt;br /&gt;
===Pippy===&lt;br /&gt;
&lt;br /&gt;
* You can edit the programs and run the changed versions.&lt;br /&gt;
* You can create your own programs. Click Clear, enter a Pythonic name to replace Pippy Activity, and Keep.&lt;br /&gt;
* You can import libraries.&lt;br /&gt;
* Turtle Art has a programmable tile that holds a single Python expression.&lt;br /&gt;
* Turtle Art has a programmable tile that reads tamyblock.py. Right-click on it in the Journal to open it in Pippy.&lt;br /&gt;
* Python is a large programming language. How do I learn it?&lt;br /&gt;
* How do I tackle the [http://api.sugarlabs.org/ Sugar API]?&lt;br /&gt;
* What is the difference between Keeping as a Python file and as a bundle?&lt;br /&gt;
&lt;br /&gt;
===Turtle Art===&lt;br /&gt;
&lt;br /&gt;
* Color space: The image below shows the colors that the Turtle draws for inputs in the range 0-399. The range repeats after 200. The 100-199 and 300-399 ranges are the reverse of the 0-99 and 200-299 ranges.&lt;br /&gt;
[[File:TA_Colors.png]]&lt;br /&gt;
* Shades: The image below shows all color and shade combinations in the ranges 0-99.&lt;br /&gt;
[[File:TAShadesAndColors.png]]&lt;br /&gt;
&lt;br /&gt;
===Write===&lt;br /&gt;
&lt;br /&gt;
* When unformatted text is selected the Style menu appears with only one item visible: None. Unless the user notices the little up arrowhead and moves the cursor up to reveal the rest of the menu, Styles remain a mystery.&lt;br /&gt;
* When text is selected, and the color palette opened, clicking outside the palette window dismisses the palette. Not a problem so far. However, if the user clicks in the edit window, the previously selected text is deselected and no color applied. Clicking anywhere on the toolbar applies the color and leaves the text selected. It has been suggested in [http://www.mail-archive.com/sugar-devel@lists.sugarlabs.org/msg08918.html mailing list thread] that adding &#039;OK&#039; and &#039;Cancel&#039; buttons, as in the color palette in Paint, would solve this problem.&lt;br /&gt;
&lt;br /&gt;
===[[The Undiscoverable/Calculate|Calculate]]===&lt;br /&gt;
&lt;br /&gt;
* Graphing&lt;br /&gt;
* Help&lt;br /&gt;
&lt;br /&gt;
===Measure===&lt;br /&gt;
&lt;br /&gt;
* Frequency and amplitude settings&lt;br /&gt;
&lt;br /&gt;
===Library===&lt;br /&gt;
&lt;br /&gt;
* I&#039;m sorry, what is this for? Oh, wait, is this what the Journal was supposed to be? No, it only shows one entry for each activity. I can&#039;t list individual sessions or documents. So what is it for?&lt;br /&gt;
&lt;br /&gt;
===Browse===&lt;br /&gt;
&lt;br /&gt;
* [[The Undiscoverable/Bookmarks|Bookmarks]]&lt;br /&gt;
* You can use browse to browse the file system and .py files&lt;br /&gt;
* Uploading from Journal&lt;br /&gt;
* [[wikipedia:About:config|about]]:config    (Enter this in the address bar to see and set Browse configuration values, such as for  [[olpc:Our software#Proxy configuration]])&lt;br /&gt;
&lt;br /&gt;
===Jukebox===&lt;br /&gt;
&lt;br /&gt;
* Where is the music?&lt;br /&gt;
&lt;br /&gt;
===IRC===&lt;br /&gt;
* Change name: click on name in right bottom corner, edit, hit &amp;lt;enter&amp;gt;&lt;br /&gt;
* /join #&#039;&#039;channel&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
*How to change the autologon channels on the XoIRC application in sugar:&lt;br /&gt;
 *in terminal  enter gedit then open and edit the file ircactivity.py &lt;br /&gt;
 in .../Activities/IRC.activity subdirectory. ( install gedit with yum install.)&lt;br /&gt;
 *add &amp;quot;client.add-channel (&#039;sugar&#039;) &amp;quot;lines with the different #channels &lt;br /&gt;
 inside quotes that you want to open on startup, Then save the changed file.&lt;br /&gt;
Now autologon to those channels works on startup&lt;br /&gt;
&lt;br /&gt;
==Programming==&lt;br /&gt;
&lt;br /&gt;
We have activities for the Smalltalk, Python, and Logo languages. Etoys includes a different version of turtle graphics. We have to provide an appropriately graded curriculum on the basic concepts of programming, starting with simple actions, such as Turtle Art drawing commands. Then we have to deal with variables, subroutines, control flow, functions or methods, and so on up to object class definitions and libraries. The laptops also have FORTH and Perl installed, and we will want materials for those, starting no doubt in later grades.&lt;br /&gt;
&lt;br /&gt;
We also need to bring in the Computer Science idea that the deep structure of a program is not the surface syntax, but is much more like the trees that we build in Turtle Art.&lt;br /&gt;
&lt;br /&gt;
==Subject matter==&lt;br /&gt;
&lt;br /&gt;
Whether in math, science, music, art, or any other subjects, there is much that cannot be discovered in unguided exploration, that has taken thousands of years of human history to achieve. The chief task in building new learning materials will be discovering ways to structure learning to maximize the amount of discovery the children can achieve, with the minimum of direction.&lt;br /&gt;
&lt;br /&gt;
We also need to be clear about skills that need practice more than discovery, as in music and sports, or keyboarding or language. What is the proper balance? On this point, see Muska Mosston, The Spectrum of Teaching Styles: From Command to Discovery. Longman, 1989. ISBN 0801303508 (out of print)&lt;br /&gt;
&lt;br /&gt;
==Hardware==&lt;br /&gt;
&lt;br /&gt;
Sugar runs on hardware and there are some hardware specific interactions that can be difficult to discover. For example, the function keys (F1–F4) map to the Sugar zoom levels/neighborhood views. This mapping is evident on the OLPC XO-1 hardware, which has dedicated symbols on those keys, but not as easy to discover on generic keyboards. Similarly, there is a key dedicated to the Frame on the OLPC XO-1 keyboard. The Frame is accessed through a keyboard shortcut on a generic keyboard (Alt-Shift-F).&lt;br /&gt;
&lt;br /&gt;
Listed below are some of the undiscoverable features specific to hardware.&lt;br /&gt;
&lt;br /&gt;
===OLPC XO-1===&lt;br /&gt;
&lt;br /&gt;
* Power button: In many target countries, many will not be familiar with international symbols.&lt;br /&gt;
* Left and right &amp;quot;mouse&amp;quot; buttons: Young children may have even more trouble with left and right than grownups. For this reason, the left button is marked &#039;x&#039;, and the right button, &#039;o&#039;.&lt;br /&gt;
* Opening: The latching mechanism is a hidden part of the antennae. Readily discoverable by children, but not by all adults, some of whom have to be shown more than once. This puzzle aspect of the XO is actually beneficial in some ways.&lt;br /&gt;
* Position of antennae. They work better in a generally upright position, parallel to each other.&lt;br /&gt;
* Rotate screen button: Easy to find, but what&#039;s it for?&lt;br /&gt;
* Book reader mode and page controls: You also need to know about screen rotation to make this work properly.&lt;br /&gt;
* Keyboard switching key, replacing ×÷ on keyboards for countries and languages using a non-Latin alphabet or other kind of writing system.&lt;br /&gt;
* Keyboard sends screen the &amp;quot;erase&amp;quot; key as the ascii code NULL (back erase) and sees &amp;quot;fn+erase&amp;quot; as code DEL (forward erase).&lt;br /&gt;
&lt;br /&gt;
====Open Firmware====&lt;br /&gt;
&lt;br /&gt;
This is presently only relevant to OLPC XO hardware, which uses Open Firmware instead of a BIOS.&lt;br /&gt;
&lt;br /&gt;
On an unlocked XO,&lt;br /&gt;
&lt;br /&gt;
* At boot time, press and hold the escape key to get into Open Firmware.&lt;br /&gt;
* In the Terminal activity, execute the command &lt;br /&gt;
&lt;br /&gt;
 echo y &amp;gt; /proc/sysrq-trigger&lt;br /&gt;
&lt;br /&gt;
See [[olpc:FORTH]] for a brief introduction to the FORTH programming language, which Open Firmware is written in, plus links to other resources.&lt;br /&gt;
&lt;br /&gt;
Be careful with OFW. You can seriously mess up or brick your XO with it. You might want to experiment in gForth first.&lt;br /&gt;
&lt;br /&gt;
==Subpages==&lt;br /&gt;
&lt;br /&gt;
{{Special:PrefixIndex/{{PAGENAMEE}}/}}&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57753</id>
		<title>0.90/Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/Notes&amp;diff=57753"/>
		<updated>2010-09-30T17:20:47Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Etoys */ Added screenshots&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ Translations | [[0.90/Notes|english]] }}{{TeamHeader|Development Team|home=Development Team|roadmap_link={{Upcoming Stable Release}}/Roadmap}}&amp;lt;/noinclude&amp;gt;[[Category:Release Notes]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size:188%&amp;quot;&amp;gt;Sucrose 0.90 Release Notes&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
Sucrose 0.90 is the latest version of the Sugar learning environment: Sugar&#039;s focus is ease of use, stability, and first-class internationalization. Sugar is Free and Open Source Software and provides tools for learning. Furthermore, Sugar provides a flexible and powerful platform for activity developers. Sugar consists of [[Taxonomy#Glucose:_The_base_Sugar_environment|Glucose]], the base system environment; and [[Taxonomy#Fructose:_The_set_of_demonstration_activities|Fructose]], a set of demonstration activities. This new release contains many new features, performance and code improvements, bug fixes, and translations.&lt;br /&gt;
&lt;br /&gt;
== What is new for users ==&lt;br /&gt;
=== Remove the Presence Service ===&lt;br /&gt;
Tomeu Vizoso from Collabora has been doing a great work to remove the [[Features/Remove_Presence_Service |Presence Service]]. There are no directly visible changes for the user but the overall collaboration experience should be more stable.&lt;br /&gt;
&lt;br /&gt;
=== Sugar Ad-hoc networks ===&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. The [[Features/Sugar_Adhoc_Networks| Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. Simon Schampijer from OLPC has been working on this Feature and back ported it as well to Sugar 0.84.&lt;br /&gt;
&lt;br /&gt;
=== Enhanced color selector ===&lt;br /&gt;
A new [[Features/Enhanced color selector| color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. Originally proposed for 0.88 this Feature went through several design iterations and finally consensus was reached. Now, we are excited to hear what the learners think about it.&lt;br /&gt;
&lt;br /&gt;
=== Spiral Home View ===&lt;br /&gt;
Walter Bender has been working on another Feature during this cycle. [[Features/Spiral_Home_View |The Spiral Home View]] is an enhancement to the Home View to enable the display of more icons. The idea is that after the circle becomes too large, rather than shrinking the icons, it morphs into a spiral.&lt;br /&gt;
&lt;br /&gt;
=== New ordering options in the Journal ===&lt;br /&gt;
Andrés Ambrois has been adding [[Features/Journal_Sort | new filtering options]] to the Journal. You can order now by size, creation date and modification date. The Feature originally implemented for [[Dextrose]] and sponsored by [http://activitycentral.org activity central] has been found it&#039;s way successfully into 0.90, too.&lt;br /&gt;
&lt;br /&gt;
=== New Keybindings for the Frame and Journal ===&lt;br /&gt;
Daniel Drake has been adding keybindings for the Journal (F5) and the Frame (F6). This will help to access those important views quicker on hardware where there is no designated key.&lt;br /&gt;
&lt;br /&gt;
=== Turtle Art ===&lt;br /&gt;
&lt;br /&gt;
The most visible changes are the incorporation of some new blocks, such as the &#039;Fill&#039; block for created filled polygons, Gray, Black, and White blocks, and the &#039;Turtle Sees&#039; block, that enables the turtle to directly interact with its canvas. There is also a [http://turtleartsite.appspot.com/ new site] for uploading and downloading Turtle Art projects.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:TAMaze.png|Turtle &#039;sees&#039;&lt;br /&gt;
File:Turtle Art Site.png|http://turtleartsite.appspot.com/&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please see [[0.90/TurtleArt]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Etoys ===&lt;br /&gt;
Sugar 0.90 includes the latest Etoys release. Some of the new features in Etoys 4.1 are DrGeo, speech bubbles, a timer tile and settable preferences. Also, the QuickGuides have been translated into several languages.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Etoys41-DrGeo.png|DrGeo in Etoys&lt;br /&gt;
File:Etoys41-Bubble.png|Speech Bubbles&lt;br /&gt;
File:Etoys41-Guide.png|Translated QuickGuide &lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Find out more in the [http://squeakland.org/download/releaseNotes.jsp 4.1 release notes].&lt;br /&gt;
&lt;br /&gt;
=== Sugar Activities ===&lt;br /&gt;
&lt;br /&gt;
While we bundle a small subset of the Sugar Activities within Sucrose, most of the Activity &amp;quot;activity&amp;quot; can be tracked by visiting [http://activities.sugarlabs.org the Sugar Activity Library]. &lt;br /&gt;
&lt;br /&gt;
We have recently surpassed &#039;&#039;3.6-million&#039;&#039; Sugar Activity downloads! There are &#039;&#039;hundreds of activities&#039;&#039; available for download in a variety of categories! &lt;br /&gt;
&lt;br /&gt;
Thanks to &#039;&#039;&#039;&#039;&#039;all&#039;&#039;&#039; the activity maintainers and developers&#039;&#039; for making this happen.&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Category !! No. of Activities&lt;br /&gt;
|-&lt;br /&gt;
|Search &amp;amp;amp; discovery||36&lt;br /&gt;
|-&lt;br /&gt;
|Documents||13&lt;br /&gt;
|-&lt;br /&gt;
|News||3&lt;br /&gt;
|-&lt;br /&gt;
|Chat, mail and talk||6&lt;br /&gt;
|-&lt;br /&gt;
|Media creation||25&lt;br /&gt;
|-&lt;br /&gt;
|Programming||13&lt;br /&gt;
|-&lt;br /&gt;
|Maths &amp;amp;amp; science||85&lt;br /&gt;
|-&lt;br /&gt;
|Maps &amp;amp;amp; geography||5&lt;br /&gt;
|-&lt;br /&gt;
|Media players||1&lt;br /&gt;
|-&lt;br /&gt;
|Games||60&lt;br /&gt;
|-&lt;br /&gt;
|Teacher tools||107&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Recent additions ====&lt;br /&gt;
[http://activities.sugarlabs.org/en-US/sugar/browse/type:1/cat:all?sort=newest Recent additions] include:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:DrGeo.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]&lt;br /&gt;
File:Pukallanapac.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]&lt;br /&gt;
File:ConstellationsFlashCards.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]&lt;br /&gt;
File:Gtranslator.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]&lt;br /&gt;
File:Words.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]&lt;br /&gt;
File:VNClauncher.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]&lt;br /&gt;
File:SunMoonMusicMC.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]&lt;br /&gt;
File:GetBooks.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]&lt;br /&gt;
File:StarChart.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]&lt;br /&gt;
File:XaoS.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]&lt;br /&gt;
File:TurtleArtMini.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]&lt;br /&gt;
File:SuperTux.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]&lt;br /&gt;
File:Nepohualtzintzin.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]&lt;br /&gt;
File:SlideruleA.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=3 style=&amp;quot;border: 1px solid white; border-collapse: collapse; background: #e3e4e5;&amp;quot;&lt;br /&gt;
 |-style=&amp;quot;background:#787878; color: white;&amp;quot;&lt;br /&gt;
! Activity !! Description&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4323 Dr. Geo]||Dr. Geo is an interactive geometry activity. Dr. Geo allows one to create geometric figure plus the interactive manipulation of such figure in respect with their geometric constraints. It is usable in teaching situation with students from primary or secondary level. It is simple and effective with some unique features as scripting and Smalltalk programming. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4320 Pukllanapac]||A puzzle: Move the pieces until the circles are all solid circles. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4318 Constellations Flash Cards]||This program teaches the constellations by means of a flash-card-like interface. The program draws a constellation and the student has to pick the correct name from a list of five possible choices. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4317 gtranslator]||A Sugarized version of the translation file editor &amp;quot;Gtranslator&amp;quot; The GTranslator activity allows to translate the po files locally. This should allow users without a permanent Internet access to translate off-line the localization files downloaded from the Pootle translation server and to contribute to the localization of Sugar to their own language. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4315 Words]||A multi-lingual dictionary with speech synthesis. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4311 VNC Launcher]||This activity helps you broadcast your screen to another computer. It will automatically launch a VNC server (X11vnc) and display your IP address. You can then connect and view the screen of Sugar on another conmputer using any VNC client (e.g. TigerVNC, UltraVNC Viewer, RealVNC, etc).&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4308 Sun Moon Music]||Sun-Moon Music MC - Realtime Sonic Environments for Children, Multiple MIDI Controller version. Collaborative exploration and performance encouraged. Requires 1 or more MIDI controllers.  This version of Sun-Moon Music is especially designed for collaborative exploration and performance. All MIDI control devices must be set to the same channel.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4304 Get Books]||The Get Books activity lets users search and retrieve books from a variety of sources (Internet Archive, Feedbooks, etc). It supports the OPDS protocol for book discovery.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4300 Star Chart]||This activity will display a map of the sky showing the position of the visible stars, some of the larger and brighter deep-sky objects (DSOs), the &amp;quot;classical&amp;quot; planets, the sun and the moon. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4299 XaoS]||XaoS is an interactive fractal zoomer. It allows the user to continuously to zoom in or out of a fractal in a fluid, continuous motion. This capability makes XaoS great for exploring fractals, and it’s just plain fun! &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4298 Turtle Art Mini]||Turtle Art Mini is a simple graphical programming environment. It is modeled on the Logo programming language and it emphasized graphical expression by learners new to programming. (Turtle Art Mimi is a subset of the [http://activities.sugarlabs.org/en-US/sugar/addon/4027 Turtle Art] activity – AKA Turtle Blocks)&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4297 Super Tux]||A Sugar clone of the Super Tux game.&lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4293 Abacus]||Abacus is a simple, customizable abacus activity for Sugar. &lt;br /&gt;
|-&lt;br /&gt;
||[http://activities.sugarlabs.org/en-US/sugar/addon/4222 Slide rule]||Sliderule is a simple, customizable slide rule activity for Sugar. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== New experimental activities ====&lt;br /&gt;
These are activities under development that may be of interest to Sugar users:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:ProducePuzzle.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4322 Produce Puzzle (experimental)]&lt;br /&gt;
File:Lemonade.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4321 Lemonade (experimental)]&lt;br /&gt;
File:GComprisAdministration.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4314 GCompris Administration (experimental)]&lt;br /&gt;
File:TVRadio.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4310 TV and Radio (experimental)]&lt;br /&gt;
File:FreeFromMalaria.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4309 FreeFromMalaria (experimental)]&lt;br /&gt;
File:OpenVideoChat.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4305 Open Video Chat (experimental)]&lt;br /&gt;
File:MathGraph32.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4303 MathGraph32 (experimental)]&lt;br /&gt;
File:SonataMediaPlayer.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4301 Sonata Media Player (experimental)]&lt;br /&gt;
File:Wine.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4296 Wine (experimental)]&lt;br /&gt;
File:TetrisMat-icon.png|[http://activities.sugarlabs.org/en-US/sugar/addon/4292 TetrisMat (experimental)]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is new for distributors and deployers ==&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for developers ==&lt;br /&gt;
The following changes are important for developers using the Sucrose 0.90 developer platform.&lt;br /&gt;
&lt;br /&gt;
=== Widgets ===&lt;br /&gt;
Add ErrorAlert inherited from Alert.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
Print warnings about the deprecated activity.info fields.&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
=== Activity Authors guidelines ===&lt;br /&gt;
There are still many activities that do not use the new activity toolbars introduced in 0.86. We encourage the switch to use the new toolbars as there have been huge improvements in usability (e.g. stopping an activity).&lt;br /&gt;
&lt;br /&gt;
Jim Simmons has written a guide to writing Sugar Activities (Please see [http://en.flossmanuals.net/ActivitiesGuideSugar/Introduction Make your own Sugar Activities!]) which details how to convert your activity to the new toolbars without compromising performance on old Sugar systems.&lt;br /&gt;
&lt;br /&gt;
== What&#039;s new for packagers ==&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;br /&gt;
&lt;br /&gt;
== Internationalization (i18n) and Localization (l10n) ==&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There a no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== Getting the sources ==&lt;br /&gt;
If you want to package sugar for your favorite distribution or just want to examine sugar&#039;s lovely code ;) you can find all the source code of each module at the links below. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.90.1.tar.bz2 sugar 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.90.0.tar.bz2 sugar-datastore 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.90.0.tar.bz2 sugar-toolkit 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.1.tar.bz2 sugar-base 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.1.tar.bz2 sugar-presence-service 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.90.0.tar.bz2 sugar-artwork 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2388.tar.gz etoys 4.1.2388]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; modules ===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-118.tar.bz2 Browse 118]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-34.tar.bz2 Calculate 34]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-68.tar.bz2 Chat 68]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-98.tar.bz2 TurtleArt 98]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Jukebox/Jukebox-20.tar.bz2 Jukebox 20]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Log/Log-24.tar.bz2 Log 24]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/ImageViewer/ImageViewer-15.tar.bz2 ImageViewer 15]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Write/Write-71.tar.bz2 Write 71]&lt;br /&gt;
&lt;br /&gt;
== Looking at the release cycle details ==&lt;br /&gt;
You can browse the notes of each development release in [[{{Upcoming Stable Release}}]]. Their respective sources are listed there as well. &lt;br /&gt;
&lt;br /&gt;
== Looking Forward to 0.92 ==&lt;br /&gt;
Introspection!&lt;br /&gt;
&lt;br /&gt;
Planning of the next release cycle has started at [[0.92/Roadmap]].&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
Many people contributed to this release indirectly, including testing, documentation, translation, contributing to the Wiki, outreach to education and developer communities. On behalf of the community, we give our warmest thanks to the developers and contributors who made this Sugar release possible. &lt;br /&gt;
&lt;br /&gt;
We want to especially thank:&lt;br /&gt;
* the [[Infrastructure_Team |  &#039;&#039;Infrastructure team&#039;&#039;]] which does all this great work in the background without which the development would not be possible at all,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;deployments&#039;&#039; that provide the development team with feedback from the field,&lt;br /&gt;
&lt;br /&gt;
* the [[Design_Team |  &#039;&#039;Design team&#039;&#039;]] which guided the design of features with UI changes or impact on the workflow,&lt;br /&gt;
&lt;br /&gt;
* the [[Translation_Team |  &#039;&#039;Translation team&#039;&#039;]] which makes sure that Sugar is enjoyable in the local languages of our users,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;developers&#039;&#039; that submit patches for new features and bug fixes,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;maintainers&#039;&#039; that review patches and make sure their code is shippable and which provide packagers with new tarballs,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;packagers&#039;&#039; which provide distributions with new Sugar packages,&lt;br /&gt;
&lt;br /&gt;
* the [[Sugar_on_a_Stick | &#039;&#039;SoaS team&#039;&#039;]] for providing during the development cycle a Sugar version to test with,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;testers&#039;&#039; for finding the small and bigger issues,&lt;br /&gt;
&lt;br /&gt;
* the &#039;&#039;release team&#039;&#039; and [[Development_Team | &#039;&#039;Development team&#039;&#039;]] for coordinating those efforts.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Guide.png&amp;diff=57752</id>
		<title>File:Etoys41-Guide.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Guide.png&amp;diff=57752"/>
		<updated>2010-09-30T17:19:37Z</updated>

		<summary type="html">&lt;p&gt;Bert: Screenshot of translated QuickGuides in Etoys 4.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot of translated QuickGuides in Etoys 4.1&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Bubble.png&amp;diff=57751</id>
		<title>File:Etoys41-Bubble.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Etoys41-Bubble.png&amp;diff=57751"/>
		<updated>2010-09-30T17:12:02Z</updated>

		<summary type="html">&lt;p&gt;Bert: Screenshot of Bubbles in Etoys 4.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot of Bubbles in Etoys 4.1&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=File:Etoys41-DrGeo.png&amp;diff=57749</id>
		<title>File:Etoys41-DrGeo.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=File:Etoys41-DrGeo.png&amp;diff=57749"/>
		<updated>2010-09-30T17:05:44Z</updated>

		<summary type="html">&lt;p&gt;Bert: Screenshot of DrGeo in Etoys 4.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot of DrGeo in Etoys 4.1&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/0.89.6_Notes&amp;diff=57343</id>
		<title>0.90/0.89.6 Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/0.89.6_Notes&amp;diff=57343"/>
		<updated>2010-09-22T13:58:39Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Updated */ Fix spelling of etoys&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Release Notes]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Sucrose 0.89.6 Release Notes =&lt;br /&gt;
&lt;br /&gt;
== Announcement ==&lt;br /&gt;
This is our development release number 6 in the [http://wiki.sugarlabs.org/go/0.90/Roadmap 0.90 development cycle]! This is our Release candidate!  &lt;br /&gt;
&lt;br /&gt;
We now entered [[Development_Team/Release#Hard_Code_Freeze | Hard Code Freeze]]. When the hard code freeze is in effect, each and every code change should be approved by the release team. Only critical fixes will be considered. To request approval send mail to sugar-devel@lists.sugarlabs.org, including the patch and a detailed description of the changes, the benefits and the risks. Approval will have to be granted by two members of the team. &lt;br /&gt;
&lt;br /&gt;
Thanks everyone for your great contributions!&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There are no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; (base) modules==&lt;br /&gt;
&lt;br /&gt;
===Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.89.4.tar.bz2 sugar-datastore 0.89.4]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2387.tar.gz etoys 4.1.2387]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.89.10.tar.bz2 sugar 0.89.10]&lt;br /&gt;
&lt;br /&gt;
===Not Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.89.5.tar.bz2 sugar-toolkit 0.89.5]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.0.tar.bz2 sugar-base 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.1.tar.bz2 sugar-presence-service 0.90.1]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.89.4.tar.bz2 sugar-artwork 0.89.4]&lt;br /&gt;
&lt;br /&gt;
== Glucose news ==&lt;br /&gt;
=== sugar ===&lt;br /&gt;
* Pass the contact-id to the buddy-removed signal instead of the handle {{Bug|2349}} (Tomeu Vizoso)&lt;br /&gt;
* Make sure we don&#039;t change the owner&#039;s colors because of a network event {{Bug|2348}} (Tomeu Vizoso)&lt;br /&gt;
* Commit from Sugar Labs: Translation System by user mschlager.: 361 of 363 messages translated (0 fuzzy). (Markus Schlager)&lt;br /&gt;
* Properly store and load friends {{Bug|2331}} (Tomeu Vizoso)&lt;br /&gt;
* Announce file transfer capabilities {{Bug|1603}} (Tomeu Vizoso)&lt;br /&gt;
* Reset resolver cache when connection has been established {{Bug|1940}} (Simon Schampijer)&lt;br /&gt;
* Display changed to &#039;Sugar in a window&#039; instead of &#039;Xephyr on&#039; Ticket {{Bug|2285}} (Ishan Bansal)&lt;br /&gt;
* Protected Activities Support {{Bug|2087}} (Martin Abente)&lt;br /&gt;
* Increase timeout for buddy properties queries {{Bug|2298}} (Tomeu Vizoso)&lt;br /&gt;
* Set param-register to False after a RegistrationExists error {{Bug|2296}} (Tomeu Vizoso)&lt;br /&gt;
* Change owner&#039;s jid to be hashed_pubkey@server {{Bug|2279}} (Tomeu Vizoso)&lt;br /&gt;
&lt;br /&gt;
=== sugar-datastore ===&lt;br /&gt;
* metadata-only update sets filesize property to 0 {{Bug|2229}}&lt;br /&gt;
* commit 3644fac reintroduced race condition, broke test suite {{Bug|2104}}&lt;br /&gt;
* autogen.sh: pass --enable-maintainer-mode to configure&lt;br /&gt;
&lt;br /&gt;
=== Etoys ===&lt;br /&gt;
* fix Journal saving fails in Sugar 0.82&lt;br /&gt;
* updated translations: de, ja, ta&lt;br /&gt;
* fix error when adding variable named &#039;val&#039;&lt;br /&gt;
* fix tile help balloons not being translated&lt;br /&gt;
* add button to reset saved preferences&lt;br /&gt;
* make soundReverb a preference&lt;br /&gt;
* do not hard-code squeak vm path&lt;br /&gt;
* replace == with = in shell tests&lt;br /&gt;
* fix paintbox in event theatre&lt;br /&gt;
* fix SuppliesPlayersTool guide&lt;br /&gt;
* remove MenuMakeNewFlap guide from index&lt;br /&gt;
* pop-up arrows now enabled by default&lt;br /&gt;
* new DrGeo examples project (see gallery)&lt;br /&gt;
* new home project (green border more visible)&lt;br /&gt;
* Demon Castle renamed to Etoys Castle and fixed&lt;br /&gt;
* revised guides for English and Spanish&lt;br /&gt;
* DrGeoII translations for de,es,fr,ja&lt;br /&gt;
* updated German and Japanese translations&lt;br /&gt;
* do not ship languages with too few translations (ar_SY, en_GB, km, pap, pl, zh_TW)&lt;br /&gt;
* hide distracting/not-functional preference panel buttons&lt;br /&gt;
* allow negative timer values&lt;br /&gt;
* shared flaps are not destroyed anymore when switching projects&lt;br /&gt;
* various smaller fixes&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; (base activity) modules==&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-117.tar.bz2 Browse 117]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-32.tar.bz2 Calculate 32]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Chat/Chat-67.tar.bz2 Chat 67]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/TurtleArt/TurtleArt-98.tar.bz2 TurtleArt 98]&lt;br /&gt;
&lt;br /&gt;
==Fructose news==&lt;br /&gt;
=== Chat ===&lt;br /&gt;
* Remove access to a private member of the presence service (Tomeu Vizoso)&lt;br /&gt;
&lt;br /&gt;
=== TurtleBlocks ===&lt;br /&gt;
====98====&lt;br /&gt;
* fixed palette selection bug introduced by alpha-value checking&lt;br /&gt;
&lt;br /&gt;
====97====&lt;br /&gt;
* recenter default turtle when dragged onto palette&lt;br /&gt;
* removed comment label from collapsible stacks&lt;br /&gt;
* made font smaller on the bottom-of-collapsible-stack block (#2305)&lt;br /&gt;
* rgs fixed resume problem in GNOME version (#2293)&lt;br /&gt;
* checking alpha value to block &#039;hit&#039; detection (#1852)&lt;br /&gt;
* trap and display math errors in python block (#2313)&lt;br /&gt;
&lt;br /&gt;
====96====&lt;br /&gt;
* fixed deleted-turtle ghost bug&lt;br /&gt;
&lt;br /&gt;
====95====&lt;br /&gt;
* some performance enhancements (block creation and stack dragging)&lt;br /&gt;
* removed depreciated field from desktop file (Luke Farone)&lt;br /&gt;
* fixed problem with setup.py in non-Sugar environments (Luke Farone)&lt;br /&gt;
* new example program for turtle sees block&lt;br /&gt;
* fixed broken clock example&lt;br /&gt;
* catch import error for upload (#2194)&lt;br /&gt;
* rescaling of read pixel values (#2188)&lt;br /&gt;
* turtle sees block takes into account gray and shade (#2188)&lt;br /&gt;
* hide extra turtles on clean (#2191)&lt;br /&gt;
* hide coordinate overlays on clean (#2191)&lt;br /&gt;
* reset scale, gray on clean (#2191)&lt;br /&gt;
* work-around to c-c/c-v toolbar bug (Raul Gutierrez #2050)&lt;br /&gt;
* writing config file in config directory (Luke Farone #2193)&lt;br /&gt;
* using turtle name to generate color for multiple turtles&lt;br /&gt;
* delete turtle when dragged onto the palette (#2191)&lt;br /&gt;
&lt;br /&gt;
====94====&lt;br /&gt;
* added &amp;quot;turtle sees&amp;quot; block&lt;br /&gt;
* added read_pixel block&lt;br /&gt;
* updated sample images (smaller file sizes)&lt;br /&gt;
* updated license for sample images&lt;br /&gt;
* updated nl translation&lt;br /&gt;
* fixed path problem with Exec in desktop file (Matthew Gallagher)&lt;br /&gt;
* fixed path problem with icon in turtleart.py (Matthew Gallagher)&lt;br /&gt;
* moved modules to TurtleArt subdirectory&lt;br /&gt;
* limit size of upload file (Jamie Boisture)&lt;br /&gt;
&lt;br /&gt;
====93====&lt;br /&gt;
* recenter overlays when window resizes (Jamie Boisture)&lt;br /&gt;
* added icon for Desktop mode (Jamie Boisture)&lt;br /&gt;
* support for project upload to server for Desktop mode (Jamie Boisture)&lt;br /&gt;
&lt;br /&gt;
====92====&lt;br /&gt;
* fixed sharing bug introduced in v91&lt;br /&gt;
* cleaned up cmdline processing&lt;br /&gt;
&lt;br /&gt;
====91====&lt;br /&gt;
* added black and white blocks&lt;br /&gt;
* fixed cgi escape bug (#1854)&lt;br /&gt;
* fixed bug with overzealous block resizing (#2092)&lt;br /&gt;
* speed up of refresh code (expose_cb handling)&lt;br /&gt;
&lt;br /&gt;
====90====&lt;br /&gt;
* fixed problem with keyboard accelerators: Ctrl-C, Ctrl-V, and Alt-Return&lt;br /&gt;
&lt;br /&gt;
====89====&lt;br /&gt;
* added non-interactive mode (with help from Jamie Boisture)&lt;br /&gt;
* fix problem with icon in F13&lt;br /&gt;
* block scale saved between sessions&lt;br /&gt;
&lt;br /&gt;
====88====&lt;br /&gt;
* alsroot fixed ObjectChooser bug (#2002)&lt;br /&gt;
&lt;br /&gt;
====87====&lt;br /&gt;
* added fill block&lt;br /&gt;
* added gray block&lt;br /&gt;
* fixed typo in sample code&lt;br /&gt;
* added mouse support to sample code (See&lt;br /&gt;
  http://tonyforster.blogspot.com/2010/03/mouse-support-in-turtleart.html)&lt;br /&gt;
&lt;br /&gt;
====86====&lt;br /&gt;
* More .es updates&lt;br /&gt;
&lt;br /&gt;
====85====&lt;br /&gt;
* Fixed bug loading floating point numbers from saved projects&lt;br /&gt;
* &#039;store in box&#039; accepts strings and numbers as labels&lt;br /&gt;
* New .es translations&lt;br /&gt;
&lt;br /&gt;
== What is new for packagers ==&lt;br /&gt;
New API has been added to telepathy-gabble and telepathy-salut to support the work on the collaboration framework, which results in needing 0.9.16 for tp-gabble and 0.3.13 for tp-salut.&lt;br /&gt;
&lt;br /&gt;
One of the goals of the collaboration refactoring was dropping functionality in sugar that has been implemented in [http://telepathy.freedesktop.org/wiki/Mission%20Control telepathy-mission-control], so Sugar now depends on tp-mission-control 5.4.3.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=Collaboration&amp;diff=56414</id>
		<title>Collaboration</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=Collaboration&amp;diff=56414"/>
		<updated>2010-09-03T13:31:09Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Testing */ unset XAUTHORITY&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{ GoogleTrans-en | es =show | bg =show | zh-CN =show | zh-TW =show | hr =show | cs =show | da =show | nl =show | fi =show | fr =show | de =show | el =show | hi =show | it =show | ja =show | ko =show | no =show | pl =show | pt =show | ro =show | ru =show | sv =show }}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
== Parents and kids ==&lt;br /&gt;
Collaboration in the Sugar sense is simply helping kids play together.  Kids play together all the time.  They talk, they run, they throw balls back and forth.  Sugar allows kids to talk and play and learn together.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Activities&#039;&#039;&#039; - Activities, in the Sugar world, are the programs and applications on which kids learn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Neighborhood&#039;&#039;&#039; - Kids find people to play with in their neighborhood view.  Who will be in my kids neighborhood?&lt;br /&gt;
&lt;br /&gt;
Really, that is all you need to know when everything works.&lt;br /&gt;
&lt;br /&gt;
But sometimes there are problems.&lt;br /&gt;
&lt;br /&gt;
== Technologists==&lt;br /&gt;
(School/Camp IT person, Tech Savvy Teacher, and others)&lt;br /&gt;
&lt;br /&gt;
There are two routes for collaboration.&lt;br /&gt;
&lt;br /&gt;
# You can collaborate &amp;quot;locally&amp;quot; without a server. If you remove the name of the Jabber server from your settings, or it fails to connect for some reason, then Sugar tries to connect locally. Sugar machines will be able to collaborate if they are connected to the same wireless network or wired port.  It will not work over your entire LAN, you have to be on the same segment.&lt;br /&gt;
# You connect up to a Jabber Server.  You can either use one on the Internet or you can install your own as part of an XS server installation.  To use a Jabber server, go to &#039;My Settings&#039; -&amp;gt; Network and put in the name of the server you want to use.  &lt;br /&gt;
===Local Collaboration on a Wired Network===&lt;br /&gt;
&lt;br /&gt;
To turn on local collaboration go to &#039;My Settings&#039; -&amp;gt; Network and remove the server name.  A blank setting will enable local collaboration.&lt;br /&gt;
&lt;br /&gt;
In many situations, computers in the same computer lab will automatically find each other.&lt;br /&gt;
&lt;br /&gt;
Bug {{Bug|1113}} is an example of a situation where this didn&#039;t work. Can we give people some guidance on how to make local collaboration work?&lt;br /&gt;
==Poet&#039;s Guide to Collaboration ==&lt;br /&gt;
&lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |             Activities&lt;br /&gt;
 |&lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |           Presence Service&lt;br /&gt;
 |&lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |               D- bus&lt;br /&gt;
 |&lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |             Telepathy&lt;br /&gt;
 |&lt;br /&gt;
 ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |         Telepathy-gabble &lt;br /&gt;
 |&lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |             XMPP      &lt;br /&gt;
 |&lt;br /&gt;
  -----------------------------------------------&lt;br /&gt;
 |&lt;br /&gt;
 |           Jabber Server  &lt;br /&gt;
 |             &lt;br /&gt;
  ----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
=== Activity Developers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Presence Service&#039;&#039;&#039; - The Presence Service is a set of APIs which allow developers to enable collaboration features on Sugar.&lt;br /&gt;
&lt;br /&gt;
That is all you need to know.  The rest is under the covers.&lt;br /&gt;
&lt;br /&gt;
=== Core Sugar Developers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Telepathy&#039;&#039;&#039; - Telepathy is another set of APIs which has a &#039;plug-in&#039; design so that various communication protocols can be &#039;plugged-in&#039; without affecting what the user of activity developers sees.&lt;br /&gt;
&lt;br /&gt;
=== Collaboration Developers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Telepathy-gabble&#039;&#039;&#039; - Telepathy-gabble is a plug-in backend that uses the XMPP protocol to talk to a server.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XMPP&#039;&#039;&#039; - Extensible Messaging and Presence Protocol ([[wikipedia:XMPP|XMPP]]) is an open, XML-based protocol originally aimed at near-real-time, extensible instant messaging (IM) and presence information. (buddy lists)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;XMPP Server&#039;&#039;&#039; - At the bottom to the stack is a XMPP server.  These are often referred to as jabber servers because the first popular XMPP Server was called jabberd.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
To test collaboration using a single development system, you can run multiple Sugar instances on the&lt;br /&gt;
same machine:&lt;br /&gt;
&lt;br /&gt;
* Create a test user&lt;br /&gt;
&lt;br /&gt;
 user$ sudo useradd -m test1&lt;br /&gt;
&lt;br /&gt;
* Become the test user. If $DISPLAY is not preserved, you may have to set it manually. And you may have to unset XAUTHORITY.&lt;br /&gt;
&lt;br /&gt;
 user$ sudo -i -u test1&lt;br /&gt;
 test1$ export DISPLAY=:0&lt;br /&gt;
 test1$ unset XAUTHORITY&lt;br /&gt;
&lt;br /&gt;
* Copy-paste the output of &amp;quot;xauth list&amp;quot; ran from your regular account&lt;br /&gt;
&lt;br /&gt;
 test1$ xauth add giskard.codewiz.org/unix:0  MIT-MAGIC-COOKIE-1  9be6c305b20ee7803a7280da553f170e&lt;br /&gt;
&lt;br /&gt;
* This requires your home to be world-accessible&lt;br /&gt;
&lt;br /&gt;
 test1$ cd ~user/src/sugar/sugar-jhbuild&lt;br /&gt;
 test1$ ./sugar-jhbuild run sugar-emulator&lt;br /&gt;
&lt;br /&gt;
* Repeat the above procedure as many time as desired to test N-way collaboration&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[OLPC:Collaboration Central]]&lt;br /&gt;
* [[OLPC:Activity sharing]]&lt;br /&gt;
* [[OLPC:Tubes]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Collaboration]]&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55984</id>
		<title>0.90/0.89.3 Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55984"/>
		<updated>2010-08-20T20:13:11Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Glucose news */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Release Notes]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Sucrose 0.89.3 Release Notes =&lt;br /&gt;
&lt;br /&gt;
== Announcement ==&lt;br /&gt;
This is our third release in the [http://wiki.sugarlabs.org/go/0.90/Roadmap 0.90 development cycle]!&lt;br /&gt;
&lt;br /&gt;
We now reached Feature Freeze! We are glad to announce that two Features have been pushed already. &lt;br /&gt;
&lt;br /&gt;
A [[Features/Enhanced_color_selector | new color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. We already wanted to land the Feature in 0.88 but had so many ideas that we did not reach consensus in the end. Now, we are excited to hear what the learners think about it. &lt;br /&gt;
&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. [[Features/Sugar_Adhoc_Networks |The Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. If Sugar sees no &amp;quot;known&amp;quot; network (the learner has not been connected to an currently available Access Point before) when it starts, it does autoconnect to an Ad-hoc network. First we try if there is an Ad-hoc network that is used by other learners in the area, if not we default to channel 1.&lt;br /&gt;
 &lt;br /&gt;
Another great Feature will be available in 0.89.4. [[Features/Remove_Presence_Service |This Feature]] removes the need for the Presence Service, meaning that activities and the Shell need to interact directly with non-Sugar-specific services such as Telepathy. As it touches three modules reviewing took a few more days. Since it is the mayor 0.90 Feature we gave it a deadline exception. The code has been pushed as I am writing these lines...&lt;br /&gt;
&lt;br /&gt;
Thanks everyone for your great contributions!&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There are no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; (base) modules==&lt;br /&gt;
&lt;br /&gt;
===Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.89.3.tar.bz2 sugar 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.89.3.tar.bz2 sugar-artwork 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.89.3.tar.bz2 sugar-toolkit 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.0.tar.bz2 sugar-presence-service 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.0.tar.bz2 sugar-base 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2382.tar.gz etoys 4.1.2382]&lt;br /&gt;
&lt;br /&gt;
===Not Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.89.2.tar.bz2 sugar-datastore 0.89.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
== Glucose news ==&lt;br /&gt;
=== sugar ===&lt;br /&gt;
* Repair for file transfers (Tomeu Vizoso)&lt;br /&gt;
* Journal: show error message on write failure {{Bug|1842}} (Anish Mangal)&lt;br /&gt;
* Restore sugar-launch by bundle id substring {{Bug|897}} (James Cameron)&lt;br /&gt;
* Add default Ad-hoc networks {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
* Fixed text overflow in About my Computer CP section {{Bug|1980}} (Tim McNamara)&lt;br /&gt;
* Added enhanced color selector: cycle through previous and next stroke and fill colors instead of random (Walter Bender)&lt;br /&gt;
* Add touchpad device to Frame for switching between capacitive and resistive modes (Walter Bender)&lt;br /&gt;
&lt;br /&gt;
===sugar-artwork===&lt;br /&gt;
* Alternative to Create a new wireless network. {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
&lt;br /&gt;
=== sugar-toolkit ===&lt;br /&gt;
* Print warnings about the deprecated activity.info fields (Simon Schampijer)&lt;br /&gt;
* Add ErrorAlert inherited from Alert (Anish Mangal)&lt;br /&gt;
&lt;br /&gt;
=== sugar-presence-service ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== sugar-base ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== etoys ===&lt;br /&gt;
* switched to etoys.squeak.org/svn repo&lt;br /&gt;
* translations broken up in smaller files&lt;br /&gt;
* activity version will not track etoys version anymore&lt;br /&gt;
* QuickGuides translated to Spanish, Portuguese, German, Italian, and (some) French&lt;br /&gt;
* added DrGeo for exploring geometry&lt;br /&gt;
* sketches support flipping&lt;br /&gt;
* geometry tiles for the world&lt;br /&gt;
* timer tile (world and other playfields)&lt;br /&gt;
* can store preferences&lt;br /&gt;
* plus bug fixes&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; (base activity) modules==&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-117.tar.bz2 Browse 117]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-32.tar.bz2 Calculate 32]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
&lt;br /&gt;
==Fructose news==&lt;br /&gt;
No news.&lt;br /&gt;
&lt;br /&gt;
== What is new for packagers ==&lt;br /&gt;
Nothing new as of today.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55983</id>
		<title>0.90/0.89.3 Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55983"/>
		<updated>2010-08-20T20:11:50Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Fructose (base activity) modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Release Notes]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Sucrose 0.89.3 Release Notes =&lt;br /&gt;
&lt;br /&gt;
== Announcement ==&lt;br /&gt;
This is our third release in the [http://wiki.sugarlabs.org/go/0.90/Roadmap 0.90 development cycle]!&lt;br /&gt;
&lt;br /&gt;
We now reached Feature Freeze! We are glad to announce that two Features have been pushed already. &lt;br /&gt;
&lt;br /&gt;
A [[Features/Enhanced_color_selector | new color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. We already wanted to land the Feature in 0.88 but had so many ideas that we did not reach consensus in the end. Now, we are excited to hear what the learners think about it. &lt;br /&gt;
&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. [[Features/Sugar_Adhoc_Networks |The Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. If Sugar sees no &amp;quot;known&amp;quot; network (the learner has not been connected to an currently available Access Point before) when it starts, it does autoconnect to an Ad-hoc network. First we try if there is an Ad-hoc network that is used by other learners in the area, if not we default to channel 1.&lt;br /&gt;
 &lt;br /&gt;
Another great Feature will be available in 0.89.4. [[Features/Remove_Presence_Service |This Feature]] removes the need for the Presence Service, meaning that activities and the Shell need to interact directly with non-Sugar-specific services such as Telepathy. As it touches three modules reviewing took a few more days. Since it is the mayor 0.90 Feature we gave it a deadline exception. The code has been pushed as I am writing these lines...&lt;br /&gt;
&lt;br /&gt;
Thanks everyone for your great contributions!&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There are no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; (base) modules==&lt;br /&gt;
&lt;br /&gt;
===Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.89.3.tar.bz2 sugar 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.89.3.tar.bz2 sugar-artwork 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.89.3.tar.bz2 sugar-toolkit 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.0.tar.bz2 sugar-presence-service 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.0.tar.bz2 sugar-base 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2382.tar.gz etoys 4.1.2382]&lt;br /&gt;
&lt;br /&gt;
===Not Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.89.2.tar.bz2 sugar-datastore 0.89.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
== Glucose news ==&lt;br /&gt;
=== sugar ===&lt;br /&gt;
* Repair for file transfers (Tomeu Vizoso)&lt;br /&gt;
* Journal: show error message on write failure {{Bug|1842}} (Anish Mangal)&lt;br /&gt;
* Restore sugar-launch by bundle id substring {{Bug|897}} (James Cameron)&lt;br /&gt;
* Add default Ad-hoc networks {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
* Fixed text overflow in About my Computer CP section {{Bug|1980}} (Tim McNamara)&lt;br /&gt;
* Added enhanced color selector: cycle through previous and next stroke and fill colors instead of random (Walter Bender)&lt;br /&gt;
* Add touchpad device to Frame for switching between capacitive and resistive modes (Walter Bender)&lt;br /&gt;
&lt;br /&gt;
===sugar-artwork===&lt;br /&gt;
* Alternative to Create a new wireless network. {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
&lt;br /&gt;
=== sugar-toolkit ===&lt;br /&gt;
* Print warnings about the deprecated activity.info fields (Simon Schampijer)&lt;br /&gt;
* Add ErrorAlert inherited from Alert (Anish Mangal)&lt;br /&gt;
&lt;br /&gt;
=== sugar-presence-service ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== sugar-base ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== etoys ===&lt;br /&gt;
* fix DBus service methods&lt;br /&gt;
* fix NavBar not showing Sugar buttons&lt;br /&gt;
* fix &#039;length&#039; and &#039;width&#039; being read-only&lt;br /&gt;
* flip commands renamed to &#039;flip left right&#039; and &#039;flip up down&#039;&lt;br /&gt;
* fix QuickGuides showing up twice&lt;br /&gt;
&lt;br /&gt;
==== Changes since 4.0 ====&lt;br /&gt;
* switched to etoys.squeak.org/svn repo&lt;br /&gt;
* translations broken up in smaller files&lt;br /&gt;
* activity version will not track etoys version anymore&lt;br /&gt;
* QuickGuides translated to Spanish, Portuguese, German, Italian, and (some) French&lt;br /&gt;
* added DrGeo for exploring geometry&lt;br /&gt;
* sketches support flipping&lt;br /&gt;
* geometry tiles for the world&lt;br /&gt;
* timer tile (world and other playfields)&lt;br /&gt;
* can store preferences&lt;br /&gt;
* plus bug fixes&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; (base activity) modules==&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-117.tar.bz2 Browse 117]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-32.tar.bz2 Calculate 32]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Etoys/Etoys-116.tar.gz Etoys 116]&lt;br /&gt;
&lt;br /&gt;
==Fructose news==&lt;br /&gt;
No news.&lt;br /&gt;
&lt;br /&gt;
== What is new for packagers ==&lt;br /&gt;
Nothing new as of today.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
	<entry>
		<id>https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55982</id>
		<title>0.90/0.89.3 Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.sugarlabs.org/index.php?title=0.90/0.89.3_Notes&amp;diff=55982"/>
		<updated>2010-08-20T20:11:26Z</updated>

		<summary type="html">&lt;p&gt;Bert: /* Updated */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;[[Category:Release Notes]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Sucrose 0.89.3 Release Notes =&lt;br /&gt;
&lt;br /&gt;
== Announcement ==&lt;br /&gt;
This is our third release in the [http://wiki.sugarlabs.org/go/0.90/Roadmap 0.90 development cycle]!&lt;br /&gt;
&lt;br /&gt;
We now reached Feature Freeze! We are glad to announce that two Features have been pushed already. &lt;br /&gt;
&lt;br /&gt;
A [[Features/Enhanced_color_selector | new color selector]] is available for the control panel, thanks to the ongoing efforts of Walter Bender and the design team. We already wanted to land the Feature in 0.88 but had so many ideas that we did not reach consensus in the end. Now, we are excited to hear what the learners think about it. &lt;br /&gt;
&lt;br /&gt;
To mimic the mesh behavior on devices where mesh hardware is not available and make the &amp;quot;under a tree&amp;quot;-scenario possible the Sugar Ad-hoc networks have been added. [[Features/Sugar_Adhoc_Networks |The Feature]] will add three default Ad-hoc networks, for channel 1, 6 and 11. They will be represented with designated icons in the neighborhood view. If Sugar sees no &amp;quot;known&amp;quot; network (the learner has not been connected to an currently available Access Point before) when it starts, it does autoconnect to an Ad-hoc network. First we try if there is an Ad-hoc network that is used by other learners in the area, if not we default to channel 1.&lt;br /&gt;
 &lt;br /&gt;
Another great Feature will be available in 0.89.4. [[Features/Remove_Presence_Service |This Feature]] removes the need for the Presence Service, meaning that activities and the Shell need to interact directly with non-Sugar-specific services such as Telepathy. As it touches three modules reviewing took a few more days. Since it is the mayor 0.90 Feature we gave it a deadline exception. The code has been pushed as I am writing these lines...&lt;br /&gt;
&lt;br /&gt;
Thanks everyone for your great contributions!&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
There are no known compatibility issues, as of today.&lt;br /&gt;
&lt;br /&gt;
== Update to this version ==&lt;br /&gt;
Please use the instructions for your distribution (SoaS, Fedora, Ubuntu, Debian etc) of choice to upgrade to this release. Note that it may take a while until the release is packaged for each distribution. Please stay tuned for distribution specific announcements and watch out for updates at [[Downloads|Get Sugar]].&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;abbr title=&amp;quot;Glucose, the base Sugar environment&amp;quot;&amp;gt;Glucose&amp;lt;/abbr&amp;gt; (base) modules==&lt;br /&gt;
&lt;br /&gt;
===Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar/sugar-0.89.3.tar.bz2 sugar 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-artwork/sugar-artwork-0.89.3.tar.bz2 sugar-artwork 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-toolkit/sugar-toolkit-0.89.3.tar.bz2 sugar-toolkit 0.89.3]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-presence-service/sugar-presence-service-0.90.0.tar.bz2 sugar-presence-service 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-base/sugar-base-0.90.0.tar.bz2 sugar-base 0.90.0]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/etoys/etoys-4.1.2382.tar.gz etoys 4.1.2382]&lt;br /&gt;
&lt;br /&gt;
===Not Updated===&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/sugar-datastore/sugar-datastore-0.89.2.tar.bz2 sugar-datastore 0.89.2]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/glucose/hulahop/hulahop-0.7.1.tar.bz2 hulahop 0.7.1]&lt;br /&gt;
&lt;br /&gt;
== Glucose news ==&lt;br /&gt;
=== sugar ===&lt;br /&gt;
* Repair for file transfers (Tomeu Vizoso)&lt;br /&gt;
* Journal: show error message on write failure {{Bug|1842}} (Anish Mangal)&lt;br /&gt;
* Restore sugar-launch by bundle id substring {{Bug|897}} (James Cameron)&lt;br /&gt;
* Add default Ad-hoc networks {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
* Fixed text overflow in About my Computer CP section {{Bug|1980}} (Tim McNamara)&lt;br /&gt;
* Added enhanced color selector: cycle through previous and next stroke and fill colors instead of random (Walter Bender)&lt;br /&gt;
* Add touchpad device to Frame for switching between capacitive and resistive modes (Walter Bender)&lt;br /&gt;
&lt;br /&gt;
===sugar-artwork===&lt;br /&gt;
* Alternative to Create a new wireless network. {{Bug|1610}} (Simon Schampijer)&lt;br /&gt;
&lt;br /&gt;
=== sugar-toolkit ===&lt;br /&gt;
* Print warnings about the deprecated activity.info fields (Simon Schampijer)&lt;br /&gt;
* Add ErrorAlert inherited from Alert (Anish Mangal)&lt;br /&gt;
&lt;br /&gt;
=== sugar-presence-service ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== sugar-base ===&lt;br /&gt;
* bump version number&lt;br /&gt;
&lt;br /&gt;
=== etoys ===&lt;br /&gt;
* fix DBus service methods&lt;br /&gt;
* fix NavBar not showing Sugar buttons&lt;br /&gt;
* fix &#039;length&#039; and &#039;width&#039; being read-only&lt;br /&gt;
* flip commands renamed to &#039;flip left right&#039; and &#039;flip up down&#039;&lt;br /&gt;
* fix QuickGuides showing up twice&lt;br /&gt;
&lt;br /&gt;
==== Changes since 4.0 ====&lt;br /&gt;
* switched to etoys.squeak.org/svn repo&lt;br /&gt;
* translations broken up in smaller files&lt;br /&gt;
* activity version will not track etoys version anymore&lt;br /&gt;
* QuickGuides translated to Spanish, Portuguese, German, Italian, and (some) French&lt;br /&gt;
* added DrGeo for exploring geometry&lt;br /&gt;
* sketches support flipping&lt;br /&gt;
* geometry tiles for the world&lt;br /&gt;
* timer tile (world and other playfields)&lt;br /&gt;
* can store preferences&lt;br /&gt;
* plus bug fixes&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;abbr title=&amp;quot;Fructose, the base set of demonstration activities&amp;quot;&amp;gt;Fructose&amp;lt;/abbr&amp;gt; (base activity) modules==&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Pippy/Pippy-37.tar.bz2 Pippy 37]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Browse/Browse-117.tar.bz2 Browse 117]&lt;br /&gt;
* [http://download.sugarlabs.org/sources/sucrose/fructose/Calculate/Calculate-32.tar.bz2 Calculate 32]&lt;br /&gt;
&lt;br /&gt;
==Fructose news==&lt;br /&gt;
No news.&lt;br /&gt;
&lt;br /&gt;
== What is new for packagers ==&lt;br /&gt;
Nothing new as of today.&lt;/div&gt;</summary>
		<author><name>Bert</name></author>
	</entry>
</feed>