App Developer Week -- Unity: Integrating with Launcher and Places -- kamstrup -- Wed, Apr 13th, 2011

   1 [21:02] <kamstrup> Hi all!
   2 [21:02] <kamstrup> So I guess I am up now
   3 [21:02] <kamstrup> My name is Mikkel Kamstrup Erlandsen and i work for Canonical on the DX team
   4 [21:02] <kamstrup> In my spare time I also dabble with software, namely Zeitgeist and search engines
   5 [21:03] <kamstrup> On the DX team I am working on all the backend and infrastructure stuff
   6 [21:03] <kamstrup> so not so much all the fancy graphics you see in Unity
   7 [21:03] <kamstrup> but all that goes on beneath it :-)
   8 [21:03] <kamstrup> In particular relevant for this session libunity
   9 [21:04] <kamstrup> libunity is a library with the purpose of instrumenting and integrating with Unity
  10 [21:04] <kamstrup> For the Natty cycle you'll be able to integrate with the Launcher and the Places/Lenses
  11 [21:05] <kamstrup> (btw for this session I'll call it Places - but in the Oneriric cycle we'll officially change to Lenses)
  12 [21:05] <kamstrup> (it's just that "places" is in my muscle memory right now :-))
  13 [21:05] <kamstrup> One big caveat emptor before we proceed too far
  14 [21:06] <kamstrup> libunity does not currently have API or ABI stability guarantees
  15 [21:06] <kamstrup> we will work on that - promised - but we also want to ensure that the API is really really nice before we freeze it
  16 [21:06] <kamstrup> and in fact
  17 [21:06] <kamstrup> I can already guarantee that there will be slight changes when we begin the Oneiric cycle
  18 [21:07] <kamstrup> but that said
  19 [21:07] <kamstrup> You can already take libunity for a spin and do some pretty impressive stuff with it
  20 [21:07] <kamstrup> fx. both the Apps and Files places are implemented with libunity
  21 [21:07] <kamstrup> there's no "priviledged" Unity API for those two buggers
  22 [21:08] <kamstrup> anyone here will be able to do exactly what they do
  23 [21:08] <kamstrup> Before we start talking about the places let's talk about the Launcher integration
  24 [21:08] <kamstrup> The Launcher integration is a lot simpler than the places
  25 [21:09] <kamstrup> So enough with the intro talk
  26 [21:09] <kamstrup> --------------------
  27 [21:09] <kamstrup> The Unity Launcher
  28 [21:09] <kamstrup> The simplest way you can integrate with the launcher is via what is called "static quicklists"
  29 [21:09] <kamstrup> https://wiki.ubuntu.com/Unity/LauncherAPI#Static%20Quicklist%20entries
  30 [21:10] <kamstrup> If you follow that link you'll see a snippet from a normal .desktop file
  31 [21:10] <kamstrup> If you take a normal .desktop file and add [Foo Shortcut Group] entries to it like shown
  32 [21:10] <kamstrup> you can add quicklist right there
  33 [21:11] <kamstrup> Look at your own /usr/share/applications/evolution.desktop for a live example
  34 [21:12] <kamstrup> What static quicklist elements can basically do is launch an executable
  35 [21:12] <kamstrup> so very simple
  36 [21:12] <kamstrup> no programming required
  37 [21:12] <kamstrup> If you want to get a bit more power
  38 [21:12] <kamstrup> you need to use libunity
  39 [21:13] <kamstrup> More specifically the LauncherEntry API
  40 [21:13] <kamstrup> For the sake of the examples we'll use Python examples today, but you can also code in Vala, C
  41 [21:13] <kamstrup> (or C++ if you manually write the C calls out)
  42 [21:14] <kamstrup> You'll see the API here http://developer.ubuntu.com/api/ubuntu-11.04/GIR/python/Unity-3.0.html#Unity.LauncherEntry
  43 [21:14] <kamstrup> it may deserve mention that we are starting to push up Python docs for the libs generated via GObject Introspection to http://developer.ubuntu.com/api/
  44 [21:14] <kamstrup> Anyway
  45 [21:15] <kamstrup> Looking at the LauncherEntry docs you'll see that it only has static constructors - not conventional constructors
  46 [21:15] <kamstrup> that's because you always get a "singleton" back for the particular app
  47 [21:15] <kamstrup> Let me find an example
  48 [21:16] <kamstrup> Here http://bazaar.launchpad.net/~unity-team/libunity/trunk/view/head:/examples/launcher.py
  49 [21:16] <kamstrup> You can set 3 main properties on the launcher entry
  50 [21:16] <kamstrup> A "count" that will be displayed as a number on the top part of the tile
  51 [21:17] <kamstrup> you may have seen this on apps like Evolution displaying the number of unread mails this way
  52 [21:17] <kamstrup> Then you can add a progress bar
  53 [21:17] <kamstrup> the values for progress must be between 0 and 1
  54 [21:17] <kamstrup> (and it's a float)
  55 [21:17] <kamstrup> You can also set the urgency hint
  56 [21:18] <kamstrup> Some may know that an "urgency hint" is something you normally have on X11 windows
  57 [21:18] <kamstrup> it makes the WM flash the window icon
  58 [21:18] <kamstrup> the difference here is that the libunity urgency doesn't require a window on the screen in order to mark an app as requiring attention
  59 [21:19] <kamstrup> this can be useful for background processes like Ubuntu One or others that need to draw your attention to their icon when they don't have a window on screen somewhere
  60 [21:20] <kamstrup> The last part of the LauncherEntry API is that you can set a "dynamic quicklist"
  61 [21:20] <kamstrup> The dynamic quicklists differ from the static ones in that you can build and update them programmatically at runtime
  62 [21:21] <kamstrup> You simply have access to a libdbusmenu DbusmenuMenuItem instance that you can populate how you like
  63 [21:21] <kamstrup> ok
  64 [21:21] <kamstrup> any questions on the laucnher api before we move on?
  65 [21:22] <kamstrup> ------------
  66 [21:22] <kamstrup> so now to Places
  67 [21:22] <kamstrup> As said before the situation here is slightly regretable
  68 [21:22] <kamstrup> It's known both as Lenses and Places in Natty
  69 [21:23] <kamstrup> For Oneiric we'll change to Lenses only
  70 [21:23] <kamstrup> (also in the all the public APIs)
  71 [21:23] <kamstrup> but for now let me call them Places
  72 [21:23] <kamstrup> Places run outside the core Unity process
  73 [21:24] <kamstrup> Think of them very much like remote database that provides data for Unity to render
  74 [21:24] <kamstrup> if you've worked with modern web development frameworks or MVC in UIs think that the place provides the *model* and Unity is a generic View
  75 [21:25] <kamstrup> Of course we have the standard Apps and Files places
  76 [21:25] <kamstrup> they are not very good beginner examples unfortunately
  77 [21:25] <kamstrup> but there are a few simple examples to start from that lots of ppl have found instructive
  78 [21:25] <kamstrup> If we stick to the Python example again
  79 [21:26] <kamstrup> you can check it out from lp:~unity-team/unity-place-sample/unity-place-python
  80 [21:26] <kamstrup> or for now just browse it online at http://bazaar.launchpad.net/~unity-team/unity-place-sample/unity-place-python/files
  81 [21:27] <kamstrup> First look at python.place
  82 [21:27] <kamstrup> All places register themselves to unity via a .place file
  83 [21:27] <kamstrup> installed under /usr/share/unity/places
  84 [21:27] <kamstrup> in a .place file you specify some contact info for Unity to find you on dbus
  85 [21:28] <kamstrup> Then each place has one or more PlaceEntries
  86 [21:28] <kamstrup> A placeentry is prettymuch what maps to an icon in the launcher
  87 [21:28] <kamstrup> You'll probably have the Apps and Files entries in your launcher at the bottom
  88 [21:29] <kamstrup> For each entry you want to expose from your place's process you need a [Entry:Foo] line in the .place file
  89 [21:29] <kamstrup> The only place that actually has more than one place entry is the Apps place
  90 [21:30] <kamstrup> although the second one is hidden
  91 [21:30] <kamstrup> Try looking at /usr/share/unity/places/applications.place
  92 [21:30] <kamstrup> you'll see that [Entry:Runner] has ShowEntry=false and ShowGlobal=false
  93 [21:31] <kamstrup> First ShowEntry=false tells unity to not put a tile in the launcher bar for this place entry
  94 [21:31] <kamstrup> the ShowGlobal=false clause tells Unity to not include this entry's results when searching from the Dash
  95 [21:31] <kamstrup> aka home screen
  96 [21:31] <kamstrup> (the one you get when you hit <super>)
  97 [21:32] <kamstrup> There is in fact a spec for these .place files
  98 [21:32] <kamstrup> Check https://wiki.ubuntu.com/Unity/Lenses#Registration
  99 [21:32] <kamstrup> You'll also note that you can define a keyboard shortcut for you place
 100 [21:33] <kamstrup> And now we're talking about this
 101 [21:33] <kamstrup> A general best-practice is to *not* include your search results in the Dash
 102 [21:33] <kamstrup> that is please set ShowGlobal=false
 103 [21:34] <kamstrup> When I write my code I am as excited as anyone to get people using it
 104 [21:34] <kamstrup> but people really want a fast Dash
 105 [21:34] <kamstrup> and if we have Dash searches laucnhing off 3 http requests, 5 disk searches, and whatnot for each letter typed...
 106 [21:34] <kamstrup> so if you want to integrate with the Dash results make sure your results are:
 107 [21:35] <kamstrup> 1) almost always relevant
 108 [21:35] <kamstrup> 2) Super snappy
 109 [21:35] <kamstrup> 3) Doesn't use to many resources to compute
 110 [21:35] <kamstrup> and 1) is probably the key point
 111 [21:35] <kamstrup> So most places would just have their tile in the launcher and a keyboard shortcut
 112 [21:36] <kamstrup> Ok back to the code
 113 [21:36] <kamstrup> In the .place file you specify the dbus contact details for your place daemon
 114 [21:36] <kamstrup> this means that Unity will start your daemon via dbus activation
 115 [21:37] <kamstrup> no need to start it yourself on login or anything
 116 [21:37] <kamstrup> this way unity has a chance of not starting all daemons at once when you log in
 117 [21:37] <kamstrup> which would run the risk of hogging your disk
 118 [21:38] <kamstrup> ok
 119 [21:38] <kamstrup> now look at http://bazaar.launchpad.net/~unity-team/unity-place-sample/unity-place-python/view/head:/unity-place-python.py
 120 [21:38] <kamstrup> This is the code for the sample place daemon
 121 [21:38] <kamstrup> There are 3 concepts you need to know about when writing a place dameon
 122 [21:38] <kamstrup> that is 1) results 2) groups 3) sections
 123 [21:39] <kamstrup> each of these three have a Dee.Model associated with them
 124 [21:39] <kamstrup> Dee.Model is implement by a library called libdee which we use for almost all of the data sharing behind Unity
 125 [21:39] <kamstrup> Dee.Model is like a table that is shared between multiple processes
 126 [21:40] <kamstrup> if any one changes, adds, or removes from the model all the other processes watching that model will be notified of what's changed
 127 [21:40] <kamstrup> pretty powerful stuff
 128 [21:40] <kamstrup> this allows us to do a kind of "distributed MVC"
 129 [21:41] <kamstrup> so in one we have the place daemon that updates the results Dee.Model and Unity is watching that same model, updating the View whenever it changes
 130 [21:41] <kamstrup> So obviously the results_model contains all the search results
 131 [21:41] <kamstrup> then we have a sections_model
 132 [21:42] <kamstrup> the sections partition the results into disjoint logical components
 133 [21:42] <kamstrup> A sections should represent a "browsable" subset of the result space
 134 [21:42] <kamstrup> If you consider the space of all apps then the sections could be Video, Audio, Games, Office
 135 [21:42] <kamstrup> etc
 136 [21:43] <kamstrup> The sections contribute the elements of the dropdown embedded in the search bar
 137 [21:43] <kamstrup> you can also access the sections of a place via the right-click context menu on a place entry in the laucncher
 138 [21:43] <kamstrup> then there a groups
 139 [21:44] <kamstrup> the groups partition the visible result set into meaning subgroups
 140 [21:44] <kamstrup> If you are watching all hits from a file search the groups could be Today, Yesterdat, Last Week, Last Month, ... etc
 141 [21:45] <kamstrup> the groups_model and results_model both have a _global_ counterparts
 142 [21:46] <kamstrup> the global models are the ones used for searching from the dash
 143 [21:46] <kamstrup> (so you normally don't need those)
 144 [21:46] <kamstrup> btw
 145 [21:46] <kamstrup> the API docs for Dee.Model are here http://developer.ubuntu.com/api/ubuntu-11.04/GIR/python/Dee-0.5.html#Dee.Model
 146 [21:46] <kamstrup> The API docs for Dee are not fully true though
 147 [21:47] <kamstrup> it has been augmented with some Python sweetness
 148 [21:48] <kamstrup> There is currenlty no easy way to document this Python magic, but you can find a demo of the Python magic for Dee.Model here http://bazaar.launchpad.net/~unity-team/dee/trunk/view/head:/examples/pythontricks.py
 149 [21:49] <kamstrup> You can also find the docs for what exactly the columns are in all the different models on https://wiki.ubuntu.com/Unity/Lenses#Results%20Model
 150 [21:49] <kamstrup> One last thing I want to mention is "Activation"
 151 [21:50] <kamstrup> So places require special callbacks when activating some special results
 152 [21:50] <kamstrup> Fx.
 153 [21:50] <kamstrup> the apps place returns Apps Available for Download that open in the Software Center when you click the,m
 154 [21:50] <kamstrup> this is achieved via the Activation API
 155 [21:51] <kamstrup> you basically register a handler for a regex matching URIs or mimetypes
 156 [21:51] <ClassBot> There are 10 minutes remaining in the current session.
 157 [21:51] <kamstrup> then when unity tries to laucnh a it it looks for any places registered for launchoing that hit
 158 [21:51] <kamstrup> and does a Dbus callback to the place daemon giving it the URI to activate
 159 [21:52] <kamstrup> the place daemon then responds whether Unity should hide the Dash as a response or if the Dash should still be shown
 160 [21:52] <kamstrup> in case for Apps Availabale for Download we ask Unity to hide the dash
 161 [21:52] <kamstrup> (so we can load S-C)
 162 [21:53] <kamstrup> but if we fx. wanted to implemen
 163 [21:53] <kamstrup> implement
 164 [21:53] <kamstrup> a file browser fx
 165 [21:53] <kamstrup> then we could ask unity to keep the dash on screen, and then just clear our results_model and repopulate it with the contents of the clicked directory
 166 [21:54] <kamstrup> I guess I'll leave the rest for your own exploration
 167 [21:54] <kamstrup> So if anyone has questions don't hold back
 168 [21:55] <kamstrup> if that's not the case then let me take 2 minutes to talk about "renderers"
 169 [21:56] <kamstrup> if you browse https://wiki.ubuntu.com/Unity/Lenses#Renderers
 170 [21:56] <kamstrup> you'll see that we have a concept called renderers which you can specify in various places in the API
 171 [21:56] <ClassBot> There are 5 minutes remaining in the current session.
 172 [21:57] <ClassBot> tronda asked: How much focus is the Python based API getting?
 173 [21:57] <kamstrup> Almost as much as the C/Vala API
 174 [21:58] <kamstrup> we really want it to be a 1st class experience
 175 [21:58] <kamstrup> and honestly i almost think that the Python API is better than the Vala/C api right now :-O)
 176 [21:58] <ClassBot> tronda asked: Any plans to get browser to work with the libunity for web applications?
 177 [21:59] <kamstrup> not short term
 178 [21:59] <kamstrup> there are some far out plans, but nothing to hold your breath for :-)
 179 [21:59] <ClassBot> tronda asked: If working with a web service which is potentially slow - would one use Tracker/Zeitgest to index content. Any help from Unity to make this simpler?
 180 [22:00] <kamstrup> Because the place daemon is another process than Unity it's not super critical if web services are slow
 181 [22:00] <kamstrup> so I'd say "don't worry in most cases"
 182 [22:01] <ClassBot> alecu asked: when a lens adds item, I see that it can add a url to get the item picture from it, like the books lens does with book covers. Will this be standard?
 183 [22:01] <kamstrup> yes, yes it will
 184 [22:01] <kamstrup> i believe that you can simply insert a URL as icon and Unity will try and load it

MeetingLogs/appdevweek1104/UnityAPI (last edited 2011-04-14 07:27:05 by 178)