Dev Week -- Rocking Out with libunity -- kamstrup -- Wed, Mar 2nd, 2011

   1 [20:02] <kamstrup> Hi all, so I guess I'm next one up...
   2 [20:02] <kamstrup> And thanks to Terence Simpson for the cool talk
   3 [20:02] <kamstrup> I am Mikkel Kamstrup Erlandsen
   4 [20:02] <kamstrup> and I work on the DX team for Canonical
   5 [20:03] <kamstrup> I am working on the backend side of all things unity
   6 [20:03] <kamstrup> My work is primarily around the "places"
   7 [20:03] <kamstrup> and in my spare time I hack on Zeitgeist
   8 [20:04] <kamstrup> so its all searching and backend code for me :-)
   9 [20:04] <kamstrup> So for today
  10 [20:04] <kamstrup> It's about libunity
  11 [20:04] <kamstrup> Here's what I plan to go over:
  12 [20:04] <kamstrup>  - libunity background
  13 [20:04] <kamstrup>  - libunity feature set
  14 [20:04] <kamstrup>  - the unity launcher integration
  15 [20:05] <kamstrup>  - the unity places integration
  16 [20:05] <kamstrup>  - some working examples of ^^
  17 [20:05] <kamstrup>  - and finally a bit about what you can expect for the future of libunity
  18 [20:05] <kamstrup> Hopefully this should empower you all to go out and rock the world with awesome unity integration
  19 [20:06] <kamstrup> So first item on the agenda: About libunity
  20 [20:06] <kamstrup> It's a native library  written in Vala
  21 [20:06] <kamstrup> We use Vala to generate GObject Introspection files so we can have automagic bings for Python and friends
  22 [20:07] <kamstrup> It's important to underline that libunity is strictly a client side library
  23 [20:07] <kamstrup> that is
  24 [20:07] <kamstrup> Unity itself does *not* link to it
  25 [20:07] <kamstrup> We focus on making the API simple and fun
  26 [20:07] <kamstrup> So we've chosen to very "property based"
  27 [20:08] <kamstrup> so you get access to a bunch of object on which you set properties
  28 [20:08] <kamstrup> and that is automatically reflect on unity
  29 [20:08] <kamstrup> all of the communication it does is pretty much DBus
  30 [20:08] <kamstrup> and it leverages libdbusmenu and libdee
  31 [20:08] <kamstrup> to perform some of the more complex dbus-stuff
  32 [20:09] <kamstrup> Now let's move on to talk about the feature set of libunity
  33 [20:09] <kamstrup> Right now there are 2 main things supportedd
  34 [20:09] <kamstrup>  - the launcher inetgration
  35 [20:10] <kamstrup>    - with progress, counter, emblems, and quicklist attached to application tiles in the launcher
  36 [20:10] <kamstrup>  - and then place inetgration
  37 [20:10] <kamstrup>     - which allows you to hook into the place framework and write you own places
  38 [20:11] <kamstrup> Maybe some of you already saw the wiki page about the launccher API:
  39 [20:11] <kamstrup> let's slowly step through it
  40 [20:11] <kamstrup> looking at the first screenshot
  41 [20:12] <kamstrup> you'll see the progress bar and counter in action
  42 [20:12] <kamstrup> and the screenie below is a quicklist
  43 [20:12] <kamstrup> So if you scroll down to the Vala example
  44 [20:12] <kamstrup> you can see it's all property based
  45 [20:13] <kamstrup> all of the attributes has a _visible cousin
  46 [20:13] <kamstrup> like emblem_visible
  47 [20:13] <kamstrup> these allow you to keep the state of you variables around
  48 [20:13] <kamstrup> by just hiding the overlay
  49 [20:14] <kamstrup> there is one thing worth mentioning here
  50 [20:14] <kamstrup> it is that the quicklists are not 100% wired up on the unity side yet
  51 [20:14] <kamstrup> there are 2 ways to write quicklists
  52 [20:14] <kamstrup> "static quicklists" are there even when your app is not running
  53 [20:15] <kamstrup> these are defined inside the .desktop files for the apps
  54 [20:15] <kamstrup> then there are "dyanmic quicklists"
  55 [20:15] <kamstrup> dynamic
  56 [20:15] <kamstrup> these are created at runtime by your app
  57 [20:15] <kamstrup> and can be very funky
  58 [20:15] <kamstrup> they use the Dbusmenu API which some of you may already know from the indicators
  59 [20:16] <kamstrup> it's a powerful api that let's you create arbitrarily complex menus
  60 [20:16] <kamstrup> if you want to compile the vala example you'll need the very latest libunity from the archives
  61 [20:17] <kamstrup> that would be 3.4.6 i believe
  62 [20:17] <kamstrup> if you run the example as is, you'll need to start evolution before you run the example
  63 [20:18] <kamstrup> if you want to use the python example
  64 [20:18] <kamstrup> make sure you have the packages:
  65 [20:18] <kamstrup> gir1.2-unity-3.0
  66 [20:18] <kamstrup> gir1.2-dee-0.5
  67 [20:18] <kamstrup> so i hope you don't have trouble running that if you try
  68 [20:19] <kamstrup> don't hesitate to ask if you have trouble
  69 [20:19] <kamstrup> chances are that 50% of the other people here have the same problem
  70 [20:19] <kamstrup> Ok, that was hopefully pretty light
  71 [20:19] <kamstrup> The next thing we'll look at is the places
  72 [20:20] <kamstrup> as you may expect that's more complex
  73 [20:20] <kamstrup> There is a wiki page which gives a rought overview of the places architecture:
  74 === photerran is now known as lz0
  75 [20:20] <kamstrup> it probably can't stand for itself though
  76 [20:21] <kamstrup> The first thing unity will look for when integrating with a place is a ".place file"
  77 [20:21] <kamstrup> The .place files define the basic access point for your place
  78 [20:22] <kamstrup> It's a standard .ini or .desktop format what ever we call it
  79 [20:22] <kamstrup> [Place]
  80 [20:22] <kamstrup> DBusName=Well known bus name the place can be found under
  81 [20:22] <kamstrup> DBusObjectPath=DBus object path the place object lives at
  82 [20:22] <kamstrup> This is the main section
  83 [20:22] <kamstrup> defining the dbus name and dbus object path your place can be found on
  84 [20:22] <kamstrup> doing it like this allows you to have more than one place inside the same process
  85 [20:22] <kamstrup> although noone is doing that right now
  86 === marnux_ is now known as marnux
  87 [20:23] <kamstrup> A "place" consist of a set of "place entries"
  88 [20:23] <kamstrup> A place in itself has no icon in the launcher - it's just a container for place entries
  89 [20:23] <kamstrup> For each Place Entry you implement there will be one icon in the launcher
  90 [20:23] <kamstrup> (or you can hide it if you want)
  91 [20:24] <kamstrup> So in the .place files you specify each of the place entries you expose
  92 [20:24] <kamstrup> It can look like:
  93 [20:24] <kamstrup> [Entry:Stuff]
  94 [20:24] <kamstrup> DBusObjectPath=DBus path for the place entry (must be a direct child of Places' DBusPath)
  95 [20:24] <kamstrup> Icon=Icon for the place entry
  96 [20:24] <kamstrup> Name=Display name for the entry
  97 [20:24] <kamstrup> Description=Short description of what the entry provides. Suitable for display as tooltip or other
  98 [20:24] <kamstrup> ShowGlobal=True|False (defaults to True)
  99 [20:24] <kamstrup> ShowEntry=True|False (defaults to True)
 100 [20:24] <kamstrup> In theory Unity could just as well look all this up over DBus once it has your address from the main [Place] group in the .place file
 101 [20:25] <kamstrup> but
 102 [20:25] <kamstrup> having it in the .place file allows unity to put icons on screen even before you place has started up
 103 [20:25] <kamstrup> so this is good for startup time
 104 [20:25] <kamstrup> So going over the [Entry:Stuff]
 105 [20:25] <kamstrup> There is another dbus path for the place entry itself
 106 [20:26] <kamstrup> And you can assign an icon, name, and description
 107 [20:26] <kamstrup> ShowGlobal tells unity whether or not this entry has search result to show in the Dash
 108 [20:26] <kamstrup> Dash - aka the homescreen
 109 [20:26] <kamstrup> you get when you click the ubuntu button in the top left corner
 110 [20:27] <kamstrup> so setting ShowGlobal=False will make unity not call you when it needs to update the results for the Dash
 111 [20:27] <kamstrup> Likewise the SHowEntry
 112 [20:27] <kamstrup> it determines whether you have a tile in the Launcher on the right
 113 [20:28] <kamstrup> You can check out your  current .place files in /usr/share/unity/places
 114 [20:28] <kamstrup> You'll also notice a "Shortcut" entry in the .place files you have
 115 [20:28] <kamstrup> It defines the letter you need to press in combo with <super> to bring up the dash showing your particular place
 116 [20:29] <kamstrup> And you'll also notice
 117 [20:29] <kamstrup> that since the groups in the .place file are formatted like [Entry:NameOfEntry]
 118 === mrjazzcat-lunch is now known as mrjazzcat
 119 [20:29] <kamstrup> You can define more than one entry per .place file
 120 [20:29] <kamstrup> so far so good - given a .place file unity can now find you
 121 [20:30] <kamstrup> so before we proceed I need to talk to you about how unity shares datamodels with the place daemons
 122 [20:30] <kamstrup> There is a central library called Dee (or libdee if you will)
 123 [20:31] <kamstrup> Dee implements a set of datamodels you can share across dbus
 124 [20:31] <kamstrup> And they are like peer-2-peer models
 125 [20:31] <kamstrup> So both unity and the place daemon can modify the models
 126 [20:31] <kamstrup> although in practice it's mostly just the place daemons
 127 [20:32] <kamstrup> This makes implement searching and all that very convenient
 128 [20:32] <kamstrup> So when you search (fx. with Zzeitgeist) you don't have to collect a result set an send it to unity
 129 [20:32] <kamstrup> you simply update your model
 130 [20:32] <kamstrup> this gives a neat way to implement "incremental searches" if you want
 131 [20:33] <kamstrup> meaning - iteratively removing hits from the result set as the user types
 132 [20:33] <kamstrup> so we don't have to send the entire result set over and over
 133 [20:33] <kamstrup> you just update your model removing the rows that no longer match
 134 [20:33] <kamstrup> under the hood Dee basically sends a "diff" to all the peers sharing the model
 135 [20:34] <kamstrup> So Dee is very powerful
 136 [20:34] <kamstrup> If we go back to the wiki page...
 137 [20:34] <kamstrup>
 138 [20:35] <kamstrup> We need to establish the "terminology" on the top of the page
 139 [20:35] <kamstrup> There are three words you need to know the meaning of:
 140 [20:35] <kamstrup>  - result model
 141 [20:35] <kamstrup>  - groups model
 142 [20:35] <kamstrup>  - sections model
 143 [20:36] <kamstrup> It's probably easiest if we take the Apps place as an example
 144 [20:36] <kamstrup> The "result model" here is (surprise!) what you see when you search
 145 [20:36] <kamstrup> The "groups model" defines the user visible grouping of the result model
 146 [20:36] <kamstrup> If you open the apps place
 147 [20:37] <kamstrup> (super-a)
 148 [20:37] <kamstrup> You'll see two groups there
 149 [20:37] <kamstrup> or wait - maybe you don't just yet
 150 [20:37] <kamstrup> ... sorry
 151 [20:37] <kamstrup> But there are 3 groups - let me write them for you
 152 [20:37] <kamstrup> Installed
 153 [20:37] <kamstrup> Available for Install
 154 [20:37] <kamstrup> and Most Popular Apps
 155 [20:38] <kamstrup> These partition the result set in 3
 156 [20:38] <kamstrup> So on to the "sections"
 157 [20:38] <kamstrup> Sections in the apps place are like "Accesories", "Media", "System", ...
 158 [20:38] <kamstrup> Ie they partition not the result set, but more the "browsable space"
 159 [20:38] <kamstrup> or the entire set of items you can potentially find
 160 [20:39] <kamstrup> I think it'll be most easy for all if I spring my surprise now
 161 [20:39] <kamstrup> So the surprise is that just today I have a fully working stack supporting place daemon implementations in Python!
 162 [20:40] <kamstrup> This makes playing around with this stuff so much easier
 163 [20:40] <kamstrup> So let me point you to a fully working place implemented in Python
 164 [20:41] <kamstrup> Here:
 165 [20:41] <kamstrup> So let's dig into
 166 [20:42] <kamstrup> Let's start at line 28
 167 [20:42] <kamstrup> Here we create the Place Entry i talked about
 168 [20:42] <kamstrup> we give it some random dbus path
 169 [20:42] <kamstrup> The models we create are all DeeSharedModels
 170 [20:43] <kamstrup> On each of the models we need to call set_schema()
 171 [20:43] <kamstrup> The schema *must* be like this
 172 [20:43] <kamstrup> you can see the definitions on
 173 [20:44] <kamstrup> The "model schemas" is really just a list of GVariant or DBus signatures
 174 [20:44] <kamstrup> one signature for each column you want to have in the model
 175 [20:44] <kamstrup> and you can even shove arbitrarily complex variants in the schema
 176 [20:44] <kamstrup> it works
 177 [20:44] <kamstrup> but for unity places we only use simple types such as strings "s" and uints "u"
 178 [20:45] <kamstrup> On line 42
 179 [20:45] <kamstrup> I create the sections model
 180 [20:45] <kamstrup> i give it a bus name
 181 [20:45] <kamstrup> which the model will use to rendevouz with other models with the same name
 182 [20:45] <kamstrup> and sync up with them
 183 [20:45] <kamstrup> and on line 44 i tell the place entry that i want to use this model as my sections
 184 [20:46] <kamstrup> ditto for all the other models created in there
 185 === neversfelde_ is now known as neversfelde
 186 [20:46] <kamstrup> notice the models with a _global in the variable names
 187 [20:46] <kamstrup> these models will be used for searches via the Dash
 188 [20:47] <kamstrup> while those without global_ will be used when you search dedicated within this particular place
 189 [20:47] <kamstrup> Let's skip a bit forward an look at line 73:
 190 [20:48] <kamstrup> here I connect to a bog standard Gobject signal from the place entry
 191 [20:48] <kamstrup> The notify signal when the "active-search" property changes
 192 [20:48] <kamstrup> On line 127
 193 [20:48] <kamstrup> you'll see the callback i connect to this signal
 194 [20:49] <kamstrup> Here i simply figure out what the new search string is and I start updating the model
 195 [20:49] <kamstrup> the results model that is
 196 [20:49] <kamstrup> To keep this example simple i always just call model.clear()
 197 [20:50] <kamstrup> the "real" places - files and apps - don't do this, but they iteratively narrow down the results_model as you type
 198 [20:50] <kamstrup> but that's quite a lot more complex and it works very well without it
 199 [20:50] <kamstrup> So what does this particular place do..?
 200 [20:51] <ClassBot> There are 10 minutes remaining in the current session.
 201 [20:51] <kamstrup> It simply just splits the search string into letters and adds a hit for each letter pointing to the wikipedia article for that letter
 202 [20:51] <kamstrup> You can see it splits the results into different groups
 203 [20:51] <kamstrup> ok, I need to start wrapping up
 204 [20:52] <kamstrup> One important note:
 205 [20:52] <kamstrup> If you want to run the Python example you need a small hack for now
 206 [20:52] <kamstrup> because all the latest jazz isn't in the package archives just yet
 207 [20:52] <kamstrup> The hack you need is to take this file:
 208 [20:52] <kamstrup> and then:
 209 [20:53] <kamstrup> download it somewhere and copy it to the right location like so:
 210 [20:53] <kamstrup> sudo cp /usr/lib/pymodules/python2.7/gi/overrides/
 211 [20:53] <kamstrup> This is needed to make Dee play well with Python
 212 [20:53] <kamstrup> With that in place you should follow the guidelines in
 213 [20:55] <kamstrup> We probably don't have a lot of time to debug any problems now, but if you poke at it  and find problems don't hesitate to ping me on the #ayatana channel
 214 [20:55] <kamstrup> While I'm throwing links around - the most basic Vala example is lp:unity-place-sample
 215 [20:56] <kamstrup> but you can dig in and find an example a tad more complex - doing youtube searches
 216 [20:56] <ClassBot> There are 5 minutes remaining in the current session.
 217 [20:56] <kamstrup> You can see the list of example places here
 218 [20:56] <kamstrup> I'll try and put all illustrative examples there
 219 [20:56] <kamstrup> when new ones crop up
 220 [20:57] <kamstrup> So quickly on the future of libunity:
 221 [20:57] <kamstrup>  - We'll have API docs for C, Python, and Vala up very soon
 222 [20:57] <kamstrup>  - Dee already have good docs for C in the libdee-doc package . but we'll have Vala and Python docs for it too
 223 [20:58] <kamstrup>  - the longer term goal for libunity is to be able to integrate and instrument the entire Unity shell from top to bottom
 224 [20:58] <kamstrup> So launcher and places is just the prelimanry goodies we can deliver for Natty
 225 [20:58] <kamstrup> For N+1 you see some nice APIs to work with the various indicators and menus
 226 [20:59] <kamstrup> And lastly - a disclaimer
 227 [20:59] <kamstrup> Sorry to end with that
 228 [20:59] <kamstrup> But we can't guarantee API or ABI stability at this point
 229 [20:59] <kamstrup> we hope there will be no landslide changes
 230 [20:59] <kamstrup> but small changes will trickle in
 231 [21:00] <kamstrup> but we we'll provide stability at some point
 232 [21:00] <kamstrup> Maybe N+1 or +2
 233 [21:00] <kamstrup> and that's a wrap!
 234 [21:00] <kamstrup> Any questions can go in #ayatana

MeetingLogs/devweek1103/RockingOutwithlibunity (last edited 2011-03-03 13:26:41 by pendulum)