GNOME.ORG

24 hours a day, 7 days a week, 365 days per year...

May 16, 2012

stranger in these parts

My JSConf 2012 video is out! Check it out:

The talk is called "Stranger in these parts: A hired gun in the JS corral", and in it I talk about my experiences as a Schemer in the implementation world, with a focus on JavaScriptCore, the JS implementation of the WebKit project.

If you want, you can fetch the slides or the notes. If you were unable to play the video in the browser, you can download it directly (25 minutes, ~80 MB, CC-BY-SA).

Special thanks to the A/V team for the fine recording. My talk was the first one that used the wireless mics, and it turned out there was some intermittent interference. They corrected this in later talks by double-miking the speakers. In my case, it was fortunate that they recorded the room as well, and with (I would imagine) a fair amount of post-processing the sound is perfectly intelligible. Cheers!

Finally, there were a number of other interesting talks whose recordings are starting to come out. I especially liked David Nolen's funhouse of ClojureScript and logic programming. It was pleasantly strange to see him mention Peter Norvig's 1992 book, Paradigms of Artificial Intelligence Programming, because I did too, and I think someone else did as well. Three people mentioning a somewhat obscure 20-year-old book, what are the odds?

I also liked Vyacheslav's amusing talk on V8's optimizing compiler. He actually showed some assembler! Folks that read this webrag might find it interesting. Dan Ingalls' talk was fun too. The ending scene was pretty surreal; be sure to watch all the way through.

Thanks again to the JSConf organizers for the invitation to speak. It was a pleasure to get to hang around the lively and energetic JS community. Happy hacking, all!

Lightspark 0.5.7 released

A new version of Lightspark has been released yesterday. You can give it a try by getting the source code from launchpad. Ubuntu packages should be available shortly from our PPA

Beside a lot of small improvements this new release improves the graphics capabilities, with a focus on Flash features used by games.

Here is the changelog:

* Fixed a few memory leaks
* Improved support for BitmapData::draw
* Support for BitmapData::copyPixels
* Support for soft masking
* Support for memory usage profiling (massif compatible)

Moreover, there has been some work on implementing fully accelerated Stage3D support, it’s still in early design phase... but stay tuned.


Flattr this

Online Glom is now all Java

Over the last couple of weeks I have reimplemented just enough of the C++ libglom code as Java in Online Glom‘s gwt-glom, removing the need for java-libglom (which wrapped libglom for Java via SWIG). It’s now working and deployed on the Online Glom test server.

This makes both development and deployment much easier. It also made the source code all camelCase so it’s not offensive to the eyes of Java coders.

To replace libglom’s use of GdaSqlBuilder, I used jOOQ. That worked well, thanks to its maintainer, Lukas Eder, who was very helpful and who quickly added some API that I needed.

Now that the code is all Java I really hope that more people will look over the code and point out anything that can be improved. I still don’t know Java like I know C++ so please don’t be shy about telling me that I have made mistakes.

GWT, Javascript, and serialization

Removing the use of java-libglom let me simplify the code, because I can now send object, such as LayoutItem, to the client without needing to copy it into a separate LayoutItemDTO object that existed just because the original wasn’t serializable, so it could be sent from the server (Java) to the client (JavaScript, compiled from Java).

However, this raised some new issues. I wanted some of the objects to contain some extra cached data, so that the client code did not have to calculate it itself, often by retrieving some other related object. Right now these are extra member variables in the classes, but that prevents me from splitting the code off into a new java-glom library.

Furthermore, any class that is sent between the client and server must fully conform to the requirements of the GWT Java-to-JavaScript compiler, even if that method will not actually be run on the server. For instance, I tried to add clone() methods, for use on the server, but that broke the JavaScript compilation because it doesn’t have an equivalent for Object.clone().

Those restrictions on the Java code that is allowable on the client side (because it will be compiled to JavaScript) were particularly awkward when the compiler (or Maven, or something) refused to give me clues about what was wrong. For instance, it took me 2 frustrating days to fix this small error by breaking the code apart until only the problem code remained. At other times, there was no real error on stdout, but there were clues (in a variety of hard-to-read formats) in the HTML generated by mvn site. Or sometimes, I could see errors when building inside Eclipse, but not outside.

The GWT system works great, but something is inconsistent about how it shows errors, and it can’t be right that some compilation errors only show up when running, rather than when building.

Next steps

As much as I would like to move on to implementing editing, I need to spend some time now on getting some regression tests set up in the maven build. These must create and run temporary PostgreSQL database instances like I do in the Glom autotools build. For instance, I need to check that the new SQL-building code, using jOOQ, is really safe from SQL injection like the libglom code seems to be.

My recent changes also caused the OnlineGlomService async API to be particularly inefficient, sometimes sending far more data back to the server than should be necessary. I will try to avoid that and try to make this API smaller, to avoid so many round trips.

May 15, 2012

Zeitgeist scalability & efficiency bootcamp results

As Trever blogged yesterday, the Zeigeist team has been busy with tweaking the DB and the engine. During that process tools and benchmarks have been developed to make the tweaking and testing more interesting. Trever will be blogging about that tomorrow so make sure to check his blog.

Our end goal is  trying to scale the engine to be able to handle a few billion events just as fast as it can handle a few hundred thousand. While we are not there yet we managed to have some pretty nice stable results for the first iteration. A lot of results show more than 100% speed enhancement. In other words a lot of queries from our standard benchmarks now consume more than 50% less time to execute. Here are some graphs of our benchmarks.

Green indicates the 0.9 release

Yellow indicates the new trunk

Most notable performance enhancement is querying Zeitgeist with a specified timeframe (from data x to date y).

 

Same queries with an open timeframe also improved

 

We also have a copy of the Synapse queries benchmarked

The queries here are typical queries used to extract info from Zeitgeist. So right now the team is really happy with the initial results. For Synapse on my local DB (over a year old), all my synapse queries perform under 0.08 seconds. We still can get more out of this. The trick here was improving our indexes and our sql query generator.

Next month we will be going through another iteration.

 

 

flattr this!

Symbolic Icons

GNOME 3 introduced a new style of icons we call symbolic. Last year, Meg Ford joined the effort we kicked off with Lapo and did a great job extending the theme coverage, without us having any style guidelines in place yet. This year, we’ll have another Woman Outreach program participant joining the effort, so I’ve edited a little video introduction on how we design these icons along with a little overview of all the icon styles currently in place.

Meeting up at LinuxTag 2012

Multitasking Mind

 

Like every year, I am driving to Berlin this week to attend LinuxTag 2012 to attend the excellent program. If you want to meet up and chat about projects, technologies, Free Software or other things, send me an email or leave a comment with this post and we will arrange for it.

flattr this!

that is all folks

this is a pretty big day for me as i am handing in my master thesis today. i was working on it almost, quite, nearly and almost a year (actually a few months less, but you should got this by now). with this final act of my computer science and psychology studies i am also finally leaving those nice student rebates and student parties behind. ghosh, what nice memories i do have here. shoddy cafeteria meals, always short on money, piles of work and bad weather when you got some free time. just some of the reasons why the studies are the best years of your life, don't you agree? ;)

but i know, my personal life isn't as interesting as this: i will present parts of my thesis during this year's guadec. but more on that later. for now just this: it will be legend - wait for it - ary!

my thesis has the title "typical development processes of free and open source software projects" and aims to provide a primary scrutiny into the development processes and project management strategies of free and open source software projects. several free and open source software projects were analyzed systematically in order to identify concertedly models and processes. gnome was of course under these projects. the results were very interesting and i will try to present them to you in near future, dear reader.

until the final evaluation however i am not allowed to publish the thesis. but my professor and i are looking for ways to publish the results in near future. so in one way or another you will shortly be able to skim through my work. if you are really interested in the topic, just drop me a note, and i will arrange a "proofread" copy for you, just for you.

with a master of science in my pocket i am looking for a great place to bring in my talents and skills. i am already in contact with some awesome companies and organizations, but if you do have some offers about or including free and open source software, project management or innovative research and products, i would love to talk to you!

May 14, 2012

doing it wrong: cse in guile

Greetings, readers! It's been a little while, but not because I haven't been doing anything, or nothing worth writing about. No, the reason I haven't written recently is because the perceived range of my ignorance has been growing faster than the domain of my expertise.

Knowledge may well be something one can dominate, but ignorance must forever be a range, stretching off to a hazy horizon. Climbing the hill of JavaScript implementations has let me see farther out on that plain. I think it's only the existence of the unknown unknowns that can let one muster up the arrogance to write at all.

But back to domains and dominators later. To begin, I note that there is very little in the way of correct, current, and universal folk wisdom as to how to implement a programming language. Compiler hackers are priests of their languages, yes, but their temples are in reality more or less isolated cults, in which the values of one's Gods may be unknown or abhorrent to those of others. Witness the attention paid to loop optimizations in some languages, compared to garbage collection in others, or closures in still others.

In my ecumenical capacity as abbot of Guile and adjunct deacon of JavaScriptCore, sometimes I'm tempted to mix rites: to sprinkle the holy water of lexical scope optimizations on JS, and, apropos of this article, to exorcise common subexpressions in Scheme.

As one might well imagine, the rites of one cult must be adapted to circumstances. I implemented CSE for Guile, but I don't know if it was actually a win. In this article I'll go into what CSE is, how it works in Guile, why it probably won't survive in its present form.

cse: common subexpression elimination

I implemented a source-to-source optimization pass in Guile that eliminates common subexpressions. It actually does both more and less than that: it propagates predicates and eliminates effect-free statements as well, and these latter optimizations are why I implemented the pass in the first place.

Let me give an example. Let's imagine we implement a binary tree in Guile, using the records facility.

(use-modules (srfi srfi-9))

(define-record-type btree
  (make-btree elt left right)
  btree?
  (elt btree-elt)
  (left btree-left)
  (right btree-right))

(define *btree-null* #f)

(define (btree-cons head tail)
  (if (btree? tail)
      (let ((elt (btree-elt tail)))
        (if (< elt head)
            (make-btree elt
                        (btree-left tail)
                        (btree-cons head (btree-right tail)))
            (make-btree elt
                        (btree-cons head (btree-left tail))
                        (btree-right tail))))
      (make-btree head
                  *btree-null*
                  *btree-null*)))

That's enough to illustrate my point, I think. We have the data type, the base case, and a constructor. Of course in Haskell or something with better data types it would be much cleaner, but hey, let's roll with this.

If you look at btree-cons, it doesn't seem to be amenable in its current form to classic common subexpression elimination. People don't tend to write duplicated code. You see that I bound the temporary elt instead of typing (btree-elt btree) each time, and that was partly because of typing, and partly out of some inner efficiency puritan, telling me I shouldn't write duplicate expressions. (Cult behavior, again!)

But, note that all of these record abstractions will probably inline, instead of calling out to procedures. (They are implemented as inlinable procedures. Yes, it would be better to have cross-module inlining, but we don't, so this is what we do.) In general, syntactic abstraction in Scheme can lead to duplicate code. Apologies in advance for this eyeball-rending torrent, but here's a listing of what btree-cons reduces to, after expansion and partial evaluation:

(define (btree-cons head tail)
  (if (and (struct? tail)
           (eq? (struct-vtable tail) btree))
      (let ((elt (if (eq? (struct-vtable tail) btree)
                     (struct-ref tail 0)
                     (throw 'wrong-type-arg
                            'btree-elt
                            "Wrong type argument: ~S"
                            (list tail)
                            (list tail)))))
        (if (< elt head)
            (let ((left (if (eq? (struct-vtable tail) btree)
                            (struct-ref tail 1)
                            (throw 'wrong-type-arg
                                   'btree-left
                                   "Wrong type argument: ~S"
                                   (list tail)
                                   (list tail))))
                  (right (btree-cons
                           head
                           (if (eq? (struct-vtable tail) btree)
                               (struct-ref tail 2)
                               (throw 'wrong-type-arg
                                      'btree-right
                                      "Wrong type argument: ~S"
                                      (list tail)
                                      (list tail))))))
              (make-struct/no-tail btree elt left right))
            (let ((left (btree-cons
                          head
                          (if (eq? (struct-vtable tail) btree)
                              (struct-ref tail 1)
                              (throw 'wrong-type-arg
                                     'btree-left
                                     "Wrong type argument: ~S"
                                     (list tail)
                                     (list tail)))))
                  (right (if (eq? (struct-vtable tail) btree)
                             (struct-ref tail 2)
                             (throw 'wrong-type-arg
                                    'btree-right
                                    "Wrong type argument: ~S"
                                    (list tail)
                                    (list tail)))))
              (make-struct/no-tail btree elt left right))))
      (let ((left *btree-null*) (right *btree-null*))
        (make-struct/no-tail btree head left right))))

Again, I'm really sorry about that, and it's not just for your eyes: it's also because that's a crapload of code for what should be a simple operation. It's also redundant! There are 6 checks that btree is in fact a btree, when only one is needed semantically. (Note that the null case is not a btree, of course.)

Furthermore, all of the checks in the first arm of the if are redundant. The code above is what the optimizer produces -- which is, you know, turrible.

So, I thought, we could run a pass over the source that tries to propagate predicates, and then tries to fold predicates whose boolean value we already know.

And that's what I did. Here's what Guile's optimizer does with the function, including the CSE pass:

(define (btree-cons head tail)
  (if (and (struct? tail)
           (eq? (struct-vtable tail) btree))
      (let ((elt (struct-ref tail 0)))
        (if (< elt head)
            (let ((left (struct-ref tail 1))
                  (right (btree-cons head (struct-ref tail 2))))
              (make-struct/no-tail btree elt left right))
            (let ((left (btree-cons head (struct-ref tail 1)))
                  (right (struct-ref tail 2)))
              (make-struct/no-tail btree elt left right))))
      (let ((left *btree-null*) (right *btree-null*))
        (make-struct/no-tail btree head left right))))

This is much better. It's quite close to the source program, except the symbolic references like btree-elt have been replaced with indexed references. The type check in the predicate of the if expression propagated to all the other type checks, causing those nested if expressions to fold.

Of course, CSE can also propagate bound lexicals:

(let ((y (car x)))
  (car x))
=> (let ((y (car x)))
     y)

This is the classic definition of CSE.

but is it a win?

I should be quite pleased with the results, except that CSE makes Guile's compiler approximately twice as slow. Granted, in the long run, this should be acceptable: code is usually run many more times than it is compiled. But this is a fairly expensive pass, and yet at the same time it's not as good as it could be.

In order to get to the heart of the matter, I need to explain a little about the implementation. CSE is a post-pass, that runs after partial evaluation (peval). I tried to make it a part of peval, as the two optimizations are synergistic -- oh yes, let's revel in that word -- are you feeling it? -- but it was too complicated in the end. The reason is that in functions like this:

(define (explode btree)
  (unless (btree? btree)
    (error "not a btree" btree))
  (values (btree-head btree)
          (btree-left btree)
          (btree-right btree)))

Here we have a sequence of two expressions. Since the first one bails out if the predicate is false, we should propagate a true predicate past the first expression. This means that running CSE on an expression returns two values: the rewritten expression, given the predicates already seen; and a new set of predicates that the expression asserts. We should be able to use these new assertions to elide the type checks in the second expression. And indeed, Guile can do this.

Perhaps you can see the size of the problem now. CSE is a pass that runs over all code, building up an ordered set of expressions that were evaluated, and in what context. When it sees a new expression in a test context -- as the predicate in an if -- it checks to see if the set contains that expression (or its negation) already, in test context, and if so tries to fold the expression to true or false. Already doing this set lookup and traversal is expensive -- at least N log N in the total size of the program, with some quadratic components in the case an expression is found, and also with high constant factors due to the need for custom hash and equality predicates.

The quadratic factor comes in when walking the set to see if the elimination is valid. Consider:

(if (car x)
    (if (car x) 10 20)
    30)

Here, we should be able to eliminate the second (car x), folding to (if (car x) 10 30). However, in this one:

(if (car x)
    (begin
      (y)
      (if (car x) 10 20))
    30)

If we don't know what (y) does, then we can't fold the second test, because perhaps (y) will change the contents of the pair, x. The information that allows us to make these decisions is effects analysis. For the purposes of Guile's optimizer, (car x) has two dependencies and can cause two effects: it depends on the contents of a mutable value, and on the value of a toplevel (x), and can cause the effect of an unbound variable error when resolving the toplevel, or a type error when accessing its car. Two expressions commute if neither depends on effects that the other causes.

I stole the idea of doing a coarse effects analysis, and representing it as bits in a small integer, from V8. Guile's version is here: effects.scm. The ordered set is a form of global value numbering. See the CSE pass here: cse.scm.

The commute test is fairly cheap, but the set traversal is currently a bit expensive.

and for what?

As I have indicated, the pass does do something useful on real programs, as in the binary tree example. But it does not do all it could, and it's difficult to fix that, for a few reasons.

Unlike traditional CSE, Guile's version of it is interprocedural. Instead of operating on just one basic block or one function, it operates across nested functions as well. However, only some dependencies can commute across a function boundary. For example:

(lambda (x)
  (if (pair? x)
      (let ((y (car x)))
        (lambda ()
          (and (pair? x) (car x))))))

Can the first pair? test propagate to the second expression? It can, because pair? does not depend on the values of mutable data, or indeed on any effect. If it's true once, it will always be true.

But can we replace the second (car x) with y? No, because (car x) has a dependency on mutable data, and because we don't do escape analysis on the closure, we don't let those dependencies commute across a procedure boundary. (In this case, even if we did escape analysis, we'd have the same conclusion.)

However, not all lambda abstractions are closures. Some of them might end up being compiled to labels in the function. Scheme uses syntactically recursive procedures to implement loops, after all. But Guile's CSE does poorly for lambda expressions that are actually labels. The reason is that lexical scope is not a dominator tree.

MLton hacker Stephen Weeks says it better than I do:

Thinking of it another way, both CPS and SSA require that variable definitions dominate uses. The difference is that using CPS as an IL requires that all transformations provide a proof of dominance in the form of the nesting, while SSA doesn't. Now, if a CPS transformation doesn't do too much rewriting, then the partial dominance information that it had from the input tree is sufficient for the output tree. Hence tree splicing works fine. However, sometimes it is not sufficient.

As a concrete example, consider common-subexpression elimination. Suppose we have a common subexpression x = e that dominates an expression y = e in a function. In CPS, if y = e happens to be within the scope of x = e, then we are fine and can rewrite it to y = x. If however, y = e is not within the scope of x, then either we have to do massive tree rewriting (essentially making the syntax tree closer to the dominator tree) or skip the optimization. Another way out is to simply use the syntax tree as an approximation to the dominator tree for common-subexpression elimination, but then you miss some optimization opportunities. On the other hand, with SSA, you simply compute the dominator tree, and can always replace y = e with y = x, without having to worry about providing a proof in the output that x dominates y. (i.e. without putting y in the scope of x)

[MLton-devel] CPS vs SSA

See my article on SSA and CPS for more context.

So that's one large source of lost CSE opportunities, especially in loops.

Another large source of lost opportunities is that the Tree-IL language, which is basically a macro-expanded Scheme, has the same property that Scheme does, that the order of evaluation of operands is unspecified.

Consider the base-case clause of my btree-cons above:

(let ((left *btree-null*) (right *btree-null*))
  (make-struct/no-tail btree head left right))

Now, *btree-null* is a toplevel lookup, that might have an unbound-variable effect. We should be able to eliminate one of them, though. Why doesn't the CSE pass do it? Because in Tree-IL, the order of evaluation of the right-hand-sides of left and right is unspecified. This gives Guile some useful freedoms, but little information for CSE.

This is an instance of a more general problem, that Tree-IL might be too high-level to be useful for CSE. For example, at runtime, not all lexical references are the same -- some are local, and some reference free variables. For mutated free variables, the variable is itself in a box, so to reference it you would load the box into a local and then dereference the box. CSE should allow you to eliminate duplicate loads of the box, even in the case that it can't eliminate duplicate references into the box.

conclusion

It is nice to be able to eliminate the duplicate checks, but not at any price. Currently the bootstrapping time cost is a bit irritating. I have other ideas on how to fix that, but ultimately we probably need to re-implement CSE at some lower level. More on that in a future post. Until then, happy hacking.

IwkMail, mixing WebKit Gtk+, Camel and JQuery Mobile

In the last few weeks, as part of my work here at Igalia, I’ve been playing a bit with the concept of hybrid applications. In this case, I’ve created a basic prototype of a mail application, with its user interface completely written using JQuery Mobile, and with backend code in C and GObject. The result is iwkmail.

Screencast of iwkmail in action

Though it’s a simple experiment, I’ve added some mail basic functionality, so I could try to catch as much as possible of real requirements for how  we could improve the developers WebKit+GNOME experience creating hybrid applications.

My first conclusion is that it’s surprisingly easy and fast to develop such applications. Second, I could reuse tons of source code and modules from my old projects. This approach surely provides a way to create cool GNOME applications, using the most fashionable web client technologies.

So, you’ll get:

  • Browsing messages
  • Read/unread flags
  • Deleting messages
  • Creating and deleting mail accounts.
  • Storage protocols supported: IMAP and POP.
  • For sending mails, we support SMTP. There’s support for an outbox holding the messages to be sent.
  • A plain text composer, allowing to add attachments.

The UI is completely written in Javascript + HTML, using JQuery Mobile.

The backend side is done using Camel library inside Evolution Data Server, so we rely on a library well tested for more than 10 years.  All the code related to this is implemented in C+GObject, and I reused a good set of code from Modest, the default mail client for Nokia N810 and N900. I’ve got involved on its development for 3 years, so that’s a bunch of code I know well enough.

For communication, I use the AJAX-like JSONP protocol, and custom SoupRequest URI scheme handlers. Basically I expose some methods as iwk:addAcccount, iwk:getMessage, etc, and arguments are passed as usual in a web request. The result I obtain from this calls is a JSON object with the results of the call. Simple, and works very well.

I’ve pushed the work on github: https://github.com/jdapena/iwkmail. Feel free to try it!

Oh, I guess it’s very obvious that I did not spend too much time thinking on the project name… So, anyone proposing something that matches the IM acronym (I don’t want to rewrite the class names!) would deserve a beer.

Last, lots of thanks to Igalia for giving me the opportunity to do this experiment. As usual, fun stuff to work with.

May 13, 2012

A little status report

What I’ve done this week:

  • split the language-support-cpp-java plugin in an indentation-c-style plugin and a language-support-cpp-java plugin without the indentation part
  • read the documentation about the plugin system of anjuta

Splitting the plugin took more time and was more challenging than expected. The main problem was to understand what each method does. So I had to read much documentation. I’m not already done with this work, but I’m on a good way…

May 12, 2012

Localisation guide now available in Spanish

I just uploaded the Spanish translation of the FOSS localisation manual I wrote a while ago. Many thanks to Lucía Morado Vázquez and Silvia Rodríguez Vázquez for their work to make it happen.

It is titled "La localización al servicio de un cambio sostenible" (PDF) with subtitle "Guía de localización de software libre y de código abierto". The manual is now available in four languages (English, French, Arabic and Spanish).

I still need to find a way to publish it with the covers — we had to create the covers as separate PDF documents for the sake of our printers, and the first way I tried to combine the documents resulted in hyperlinks being lost in the resulting PDF.

Speaking of printing: we printed copies of the other three languages for our training events around Africa, but the Spanish version came later and was completely a volunteer effort separate from the activities of ANLoc. What is the best way to try to get some of these printed? I'm sure a few people would be interested in a hard copy.

PulseAudio 2.0: Twice The Goodness!

That’s right, it’s finally out! Thanks go out to all our contributors for the great work (there’s too many — see the shortlog!). The highlights of the release follow. Head over to the announcement or release notes for more details.

  • Dynamic sample rate switching by Pierre-Louis Bossart: This makes PulseAudio even more power efficient.

  • Jack detection by David Henningsson: Separate volumes for your laptop speakers and headphones, and more stuff coming soon.

  • Major echo canceller improvements by me: Based on the WebRTC.org audio processing library, we now do better echo cancellation, remove the need to fiddle with the mic volume knob and have fixed AEC between laptop speakers and a USB webcam mic.

  • A virtual surround module by Niels Ole Salscheider: Try it out for some virtual surround sound shininess!

  • Support for Xen guests by Giorgos Boutsiouki: Should make audio virtualisation in guests more efficient.

We don't always make a release, but when we do, it's awesome

Special thanks from me to Collabora for giving me some time for upstream work.

Packages are available on Gentoo, Arch, and probably soon on other distributions if they’re not already there.

May 11, 2012

Support Portal, Thin Client Updates & UI Updates

Our "support portal" and any thin client updates go hand in hand.  We control features centrally and then they are pushed to thin clients.  My current biggest project now that the GNOME desktop is deployed and LibreOffice is live is merging in all of the features we wanted to deploy in our next thin client update.  I have finished the code to allow Kiosk/POS type connections to Microsoft Windows without requiring a connection first to the City system.  For those at our Recreation sites that move around between workstations, this will be a big help.  I also have added a Help button from the thin clients that allow the users to send us email without first logging in; and they can check on the status of the servers.  We placed our reboot schedules in ICS files for Evolution users, but now the thin clients will be able to display this information as well.  I'll blog more about this with shots when it's all finished.

One feature request that's coming in this next release is the ability to support dual monitors beyond just [ LANDSCAPE ] [ LANDSCAPE].  We'll be adding [ PORTRAIT ] [ PORTRAIT ] and [ PORTRAIT ] [ LANDSCAPE ].  We are all on the same video cards, so once I get it working it deploys to everyone else with the same Xorg files, nice.  The support portal is being modified to understand what combinations work and set the appropriate configuration files for them to download at next OS update. I spent some time hacking on the thin client detail screen which now better understands the monitors, their type and what exactly is displaying on each half.  When requested, the portal breaks their current screen into two pieces and then displays it on the UI on the appropriate monitor.  Mouse over on the monitor displays all supported resolutions, and the new OS build queries their devices and returns the make and model of monitor.  This is going to save us lots of time.



I cleaned up the [ Summary ] tab which displays actionable tiles of user problems.  These are not warnings, but issues where it's mandatory for action to be taken.  I have cleaned up exactly what is displayed and done some alignments of the widgets.  In the shot below it's alerting our support staff that some printers have stuck queues, that some users had some software problems because of missing network permissions and that some users had the power drop on their workstations.  Hovering mouse over these tiles displays the problem along with the most likely way to resolve the issue.


I monitor support calls and have hallway conversations with users all the time.  The intermediate UI that comes up when you double-click on a picture from Nautilus had some issues.  It's always interesting to me to see how users react and use software, and the things that I didn't think of during the design stage.  Very often I have better ideas, but am always trying to work these issues within the hours of the day.  These changes require very few coding changes, it's just mostly about the presentation and UI.  The show below shows the old UI (left) and the new one (right).  The new UI is not yet live and a shell right now in Glade until I feel all the changes look good and then I'll move the code over -- which will be easy.  If you are interested in user interaction, here are the changes:
  • Users seem to like having art on each button, they seem to remember steps by artwork and not the words; each button now has art.
  • The users were not finding the button to PrintToSelectedPrinter easily, so the button was moved to the right of selected the printer.  No call is made to the GNOME printer UI, it has way too many options for this purpose.
  • The users were not seeing easily that you could DeliverWithEvolutionBypass (SMTP dump to Groupwise) based on the entry email box below.  This should be more clear.
  • The 'Size of This File' area while a good start; did not really tell them anything they could understand and use.  The new UI will alert them of "suitability" with Evolution and LibreOffice.  Everyone is shooting 10 megapixel now which is not needed for email and document construction.  I'll make generalized statements (Good, Too Big, Too Small, etc) about the pictures.
  • The functions that allow you to alter a photo are now under the photo; the functions to do something with the resulting output are all on the right side.
  • Users with dual screens were taking screenshots and then wanting to only print 1/2 of the screen.  The current code would print the whole width landscape which is too small.  Buttons are now available to crop the screen.  Going into GIMP and doing this by hand is too many steps for such a basic function.
  • Various alignments and layout techniques improved because I'm slowly learning Glade as time allows.


Once the code is done, I'll connect it for my user account only for testing and then release it to beta testers for wider use and then deploy citywide.  These changes are super easy on a centralized server and are literally just commenting in and out a few lines.   I'll be interested to obtain their feedback.

Maps and clocks and contact locations

Once upon a time, three intrepid individuals made Empathy publish your location to your contacts, and show your contacts’ locations on a map. Today, I noticed that the Location tab is missing from Preferences—I guess Debian’s Empathy is built without GeoClue support for some reason—and as a result the map looks rather forlorn, what with none of my contacts publishing their location:

Empathy's empty Contact Map View window

A map is an obvious demo to build, but I don’t think it’s that useful (even when it had more than zero contacts on it, I never looked at it).1 So what would be more useful? For starters, here’s some “relevant art” from Skype, showing a contact’s local time in their tooltip:

Raúl's Skype tooltip shows it's 6am where he is.

Adding that to Empathy might be a useful first step. But unlike Skype, it’s possible to use this information outside the IM app. So, if I spend a lot of time chatting to friends in Melbourne and New York, why not automatically add those timezones to GNOME Clocks? (The last two mock-ups in that section look particularly bare—perhaps the names of some contacts could show up in the space where “local time” does for Boston.)

For this to be useful, of course, someone would have to fix the publishing of location information in the first place. But if fixing it produced a more compelling feature than a map, it would not be such a thankless task.

  1. Top designers agree! To quote Allan Day, “I could live without contacts on a map ;) ”.

May 10, 2012

Promoting GOPW and GSoC in Gran Canaria

After a long holiday, I completely forgot to show you this, my latest small contribution to GNOME. From Gran Canaria, at the University of Las Palmas de Gran Canaria (ULPGC) with love...


PyGObject 3.2.1 released

I am pleased to announce version 3.2.1 of the Python bindings for
GObject. This is a maintenance release for the stable branch bringing
you a couple of bug fixes.

Download

http://download.gnome.org/sources/pygobject/3.2/pygobject-3.2.1.tar.xz

sha256sum:
0f07401289fa33e8caee7a9342f5c838bb44cd0a386cb99093505edb5e42817a

Highlights

  • Add missing override for TreeModel.iter_previous() (Martin Pitt)
  • GSettings: allow extra keyword arguments (Giovanni Campagna)
  • pygtkcompat: Correct Userlist module use (Jose Rostagno)
  • GTK overrides: Add missing keyword arguments (Martin Pitt)
  • pygi-convert.py: Drop obsolete drag method conversions (Martin Pitt)
  • Fix len_arg_index for array arguments (Bastian Winkler)
  • Add missing GObject.TYPE_GTYPE (Martin Pitt)
  • Add GtkComboBoxEntry compatibility (Paolo Borelli)

Changes

http://download.gnome.org/sources/pygobject/3.2/pygobject-3.2.1.changes

About PyGObject

GObject is a object system used by GTK+, GStreamer and other libraries.

PyGObject provides a convenient wrapper for use in Python programs when
accessing GObject libraries.

Like the GObject library itself PyGObject is licensed under the GNU
LGPL, so is suitable for use in both free software and proprietary
applications. It is already in use in many applications ranging from
small single purpose scripts up to large full featured applications.

PyGObject now dynamically accesses any GObject libraries that uses
GObject Introspection. It replaces the need for separate modules such as
PyGTK, GIO and python-gnome to build a full GNOME 3.0 application. Once
new functionality is added to gobject library it is instantly available
as a Python API without the need for intermediate Python glue.

Japan Freedom Hackers: Assemble!

Turns out I’ll get to spend the next two weeks in Tokyo, starting next Sunday. It will be third time I visit this weird and fascinating place, but I’m still excited to be there again.

Some time ago, in another trip, I proposed anyone who might be reading me to meet up and talk about all things GNOME or WebKit. Turns out I met some interesting people that way (hi everyone from Caixa Mágica!), so let’s try again: if you are reading this, are in Tokyo, and would like me to talk to your friends/colleagues/whatever about GNOME or WebKit I’d be happy to do so. We can also improvise a hackfest or anything else we can come up with. In exchange I only ask of you to show me around (always better with a local) and an unwavering commitment to freedom and justice.

Drop me a line at xan AT gnome DOT org, or leave a comment in this space.

GSoC: Overhauling the Apps view

Hello Planet!

This summer I’m going to work on overhauling the Apps view in GNOME Shell. In this I’ll be assisted by fmuellner, who is kind enough to be my mentor. Thanks Florian!

First of all, I will remove modes from the overview. Originally, the overview was intended to have more modes than the two current ones (Windows, Applications), but it was found that this would probably just add unwanted clutter. Therefore I will be removing the Apps mode from the overview and make the Apps view accessible through an icon in the dash.

Secondly, I’ll be making the Apps view paged. It will replace the current predefined categories,  Users will be able to order their apps in pages, making it easier to find the app they’re looking for – after all, they’re the ones that put it there.

This animation by jimmac will give you an idea of what I’ll be building this summer.

I’m really looking forward to this summer, and to working with the talented people who design and build GNOME Shell. If you have any questions, comments, ideas or just want me to see some pictures of your newborn kittens, don’t hesitate to leave a comment, ping me on gimpnet irc – I’m joost, I usually lurk in the #gnome-shell, #gnome-design, #soc, #gnome-hackers and #gnome-love channels – or add to my project’s wiki page - https://live.gnome.org/JoostVerdoorn_Overhauling_the_Apps_View.

Cheers!

GNOME Design Update, Part Two

I left it too long to blog about what’s been happening in GNOME design, and I’ve been left with a backlog of things to tell everyone about! In my last post, I wrote about the work the GNOME designers have been doing on the core user experience, including things like the lock screen, notifications, printing and scrolling. In this one I’m going to review application design efforts, as well as work we’ve been doing around application integration.

Application development is a major focus for us in GNOME design. We recognise that GNOME needs new, updated applications, and we’ve been making good progress in that direction. GNOME already has some new applications in the shape of Web, Documents, Contacts and Boxes. Others are starting to emerge, such as Photos, Videos and Clocks. Not only are we assisting in these ongoing application development efforts, but we are also designing other new applications, and we are also working on improving the integration between applications and GNOME 3.

Here’s our recent application work.

Clocks

Clocks is planned to be a new core app, which will provide handy tools for viewing the time in different parts of the world, alarms, setting timers and a stopwatch. Jon has elaborated his original designs recently, so that we have a fairly complete design for the app.

Hi-resolution mockups for this one come courtesy of Jimmac.

Notes

While there are notes apps for GNOME, we don’t yet have one that works well with GNOME 3 look and feel. We think there’s an opportunity to provide a new app that is both highly integrated and more refined than what we’ve had previously, and Jimmac’s stepped up to the plate to design a brand new application.

If anyone wants to help implement this design, they should definitely get in touch. I know this is something that a whole bunch of us would really like to see happen.

To Do

This one is a little personal project of mine. It’s an idea for a simple to do list application, modelled on GNOME 3 application design principles. To Do is definitely not one destined to be a core GNOME app, but it would make a good optional application, and could be a nice little hacking project for someone.

Activities Overview Search

Ensuring that applications are able to effectively integrate with GNOME 3 is also a big focus for ongoing design work. Integrated application search is one area where this has been happening.

GNOME 3.4 introduced the ability for applications to add their own search results to the Activities Overview. Documents and Contacts are doing this right now – if you are on 3.4, searching from the overview will give you results from these applications as well as displaying applications and settings panels.

In the future we want to have other apps providing search results to the overview. This will mean that a single search will tap into the full range of apps you have on your machine. We’ve been working on designs for how to display these integrated application search results and preliminary details of the new designs are on the wiki. (No pretty mockups yet, but they’ll come.)

Content Selection

One of the big aims behind GNOME 3 is to radically improve the ease with which users can find content, such as documents, music, videos and so on. It is this aim that led us to develop the new GNOME Documents application, as well as the designs for Photos, Music and Videos.

Each of the new GNOME content applications are intended to improve on the file system (and file manager) as a way to store and access content. They focus on presenting relevant content, will come with effective search facilities, and will allow you to filter content and create flexible collections.

The next step in this content story for GNOME 3 is to bring the benefits of the new content applications to selection operations. With this approach, choosing an item to attach to an email should work in exactly the same way as it does in one of the new content apps. This will closely tie the content applications in with the rest of the system.

The content selection designs are still work in progress. It’s a tricky design to get right and we’re taking our time with it. The current plan is to test a few of the patterns that make up the design before embarking on anything more adventurous.

As you can see from the mockup, the new content selection designs still include the option to use a file manager style interface, should that be required.

Application Menus

Last but not least, we’re pushing hard to achieve consistent application menu adoption for GNOME 3.6. Application menus have been planned as a feature of GNOME 3 for some time, but it was only in the last release that applications got the ability to define their own menus. Now that they have this, the challenge is to ensure that GNOME applications start using them consistently.

I recently proposed a GNOME Goal to promote the adoption of application menus, and some progress has been made. There are still a lot of bugs to be fixed though, so feel free to help out if you can.

<< Fin >>

Phew, that’s it. As you can see, the denizens of GNOME design land have been busy recently, and there’s lots of work to report on. If you would like to help make any of these designs a reality, just get in touch or look in the usual places. The future is looking really bright for GNOME, and I still get excited when I think about all the plans we have. The sooner we can get to where we want to be, the better!


F17 desktop spin facelift

There was some discussion on fedora-devel-list about how to make it more obvious that the Fedora desktop spin. Various proposals were worked out to the point of working implementations.

Kamil Paral made the start with an extension that puts an ‘Install’ button in the top bar. I’ve followed up with a notification that pops up at login, explains that you are using live media, and offers you to install (The backstory here is that we’ve actually had a shell extension for showing the installer on the desktop spin for a while before F16, but the gnome-shell team asked that we ship GNOME 3 without extensions installed, so we’ve taken it out.). The notification was never my favourite approach to this issue; I preferred to just auto-start the installer.

We are very lucky that Cosimo Cecchi and Kalev Lember teamed up for an outstanding job, and got a much nicer solution implemented, polished and integrated in a matter of days, so the initial experience when booting the F17 desktop spin will be this:

I’m looking forward to it !

Cyrillic

Allan has done a great job giving an overview of what we’ve been focusing on recently among the design team. This still leaves some room for me to give a peek on some of the details of what’s coming.

One of the decisions we made for GNOME 3 in terms of identity, was embracing Dave Crossland’s Cantarell and its open source pedigree and making the typeface our own. So far I have only been humbly shaping minor aspects of the typeface, but a long standing issue has been left long untouched, support for Cyrillic. Typeface design is certainly going outside my comfort zone. Luckily most of the glyphs can be dealt with by borrowing from their latin counterparts. The major part of the work involved (and will involve) some shape tweaks, metrics and hinting. Again, the bold weight poses bigger challenges at small sizes, which is our main focus.

Substituted cyrillic glyphs were all sorts of broken.

.

As you can see, there’s still some tweaking left to do on the shapes and hints before rolling out 0.0.9, but those not intimidated by jhbuild, please give it a go so you can help me identify issues that aren’t apprent to me. Another set Cantarell needs to support is Greek, as it’s stylistictically required to keep close to the Latin set.

Some news about GUADEC 2012 content

Notification to speakers

The GUADEC 2012 programme committee took a bit more time than first anticipated to evaluate all talk submissions, but it's now all done: this morning, we finally sent the notification to speakers. Thanks to everyone who submitted a talk: it looks like we'll have a great GUADEC :-) Of course, we still need to create the schedule, but that should be trivial, right? (hmm...)

If you submitted a talk and didn't get a positive or negative answer by mail, please first check your spam folder: mail is from guadec-papers, and contains Your talk at GUADEC 2012 in the subject. If you don't find anything, feel free to ping me.

Help organize the lightning talks!

Next step is the call for lightning talks and for BoFs! I guess this will happen in the next few days. I don't think we have anyone in charge of this yet, so if that's something you'd like to help with, just drop us a quick mail on guadec-list and we'll happily give you a I'm fantastic: I'm helping organize GUADEC badge ;-)

Quart de siècle

Today, I am turning 25 years old. Holy carp. A quarter of a century old. At this rate, how the heck can I solve the massive amount of bugs remaining in GNOME and GStreamer in only a hundred years?

Binding an implicit to a Scala instance

In several real-world cases I’ve had a pair of types like this:

An implicit often leaves a policy decision undecided. At some layer of your code, though, you want to make the decision and stick to it.

Passing around a tuple with an object and the implicit needed to invoke its methods can be awkward. If you want to work with two such tuples in the same scope, you can’t import their associated implicits, so it’s verbose too.

It would be nice to have bind[A,I](a: A, asImplicit: I), where bind(cache, cacheContext) would return the equivalent of BoundCache.

I guess this could be done with macro types someday, but probably not with the macro support in Scala 2.10.

If implemented in the language itself, it’s possible BoundCache wouldn’t need any Java-visible methods (the delegations to Cache could be generated inline).

However, one use of “bound” classes could be to adapt Scala APIs to Java. In Java you could bind one time, instead of explicitly passing implicit parameters all over the place.

Has anyone else run into this?

May 09, 2012

mongo-glib

I recently wanted to learn the mongo wire protocol so I could better understand how to optimize my queries. I'm not a huge fan of Mongo, but they do a few things well. Additionally, I wanted something that would eventually work with GObject Introspection so I have the same API in multiple languages.

Therefore, I started writing one. It takes a different approach than most of the drivers out there. Primarily, it uses the asynchronous model introduced in GIO. This of course adds some extra complexity, but allows you to pipeline some packets together which can be useful.

Additionally, there is a MongoBsonStream object that is useful for reading through a file that contains a stream of BSON documents sequentially. This is the wire format for mongodump. Therefore, if you want to do offline jobs against your mongo backups, this can be quite useful. I in fact use it to verify the BSON schema of our database offline, after backups have occurred.

I don't know what will end up happening with it, but here it is.

Mongo-GLib-0.1.9

glib mainloop sources in python (e.g. for irclib)

Rick Spencer pulled me over today to help with an IRC client that he’s working on. He’s using python irclib to talk to IRC and Gtk/Webkit for the UI. The trouble with that combination is that the two are not using the same mainloop.

We sat down for a while and finally figured out that the ‘IRC’ object in irclib has three hooks for user-provided functions to help with this:

  1. add fd watch
  2. remove fd watch
  3. add timeout

The fd watch functions are passed a python socket object to add or remove a watch for. The intent is that you will watch for the socket becoming readable. As far as I can tell, irclib always performs blocking writes on the assumption that it won’t be a problem.

GLib lacks functionality for easily hooking up watches for fds (although we have some proposals for that in bug #658020 which I will be looking at more closely soon). You can use GIOChannel but that’s always somewhat annoying and as far as I can tell cannot be used from Python with a unix fd (possibly due to a binding issue?). The remaining solution is to implement a GSource from python, which is tricky. Rick made me promise I’d blog about the code that I came up with to help with that. Here it is:

class SocketSource(GLib.Source):
    def __init__(self, callback):
        GLib.Source.__init__(self)
        self.callback = callback
        self.pollfds = []

    def prepare(self):
        return False

    def check(self):
        for pollfd in self.pollfds:
            if pollfd.revents:
                return True

        return False

    def dispatch(self, callback, args):
        self.callback()
        return True

    def add_socket(self, socket):
        pollfd = GLib.PollFD(socket.fileno(), GLib.IO_IN)
        self.pollfds.append(pollfd)
        self.add_poll(pollfd)

    def rm_socket(self, socket):
        fd = socket.fileno()
        for pollfd in self.pollfds:
            if pollfd.fd == fd:
                self.remove_poll(pollfd)
                self.pollfds.remove(pollfd)

The callback function provided to the constructor is called when one of the sockets becomes ready for reading. That maps nicely for irclib’s process_once function. The add_socket and rm_socket fit nicely with irclib’s fn_to_add_socket and fn_to_remove_socket. Using the code looks something like so:

simple = irclib.SimpleIRCClient()
source = Socketsource(simple.ircobj.process_once)
simple.ircobj.fn_to_add_socket = source.add_socket
simple.ircobj.fn_to_remove_socket = source.rm_socket
source.attach()

Timeouts are left as an exercise to the reader.

2012-05-09: Wednesday

  • Up lateish; mail, patch review, merge, cherry-picking etc. Dug into grammar checker related slowness from Daniel's nice notes. Poked away at scripting, and mailing people, worked late.

« Travel assistance applications to attend to GUADEC 2012

Dear hackers,

The GNOME Foundation provides travel sponsorships to individuals that want to attend GUADEC and need financial assistance.

As we announced by email, the Travel Committee is receiving applications for sponsorships to attend to GUADEC 2012. This year, GUADEC is being held in the University of A Coruña, Spain, from Thursday 26th July until Wednesday 1st August.

The instructions are detailed at http://live.gnome.org/Travel. Please read them carefully.

Deadline: May 16, 2012, 23:59 UTC.

Milenium
A Coruña

Some additional comments:

  • Any information you send to the Travel Committee will be private. Asking for sponsorship does not guarantee you will get sponsored.
  • A good application with good information will be processed faster.
  • If you need help with accommodation, the Travel Committee will book the hotel or hostel for you. This enables us to get group rates and provide accommodation assistance to the most people possible.
    You should state that you need accommodation, and leave the cost blank.
  • Always choose the most economical option whenever possible. People who need travel sponsorship, should look for the best price (i.e. through a service like kayak.com). If the Travel Committee finds a cheaper price, that will be the price considered during the evaluation.
  • If you are applying to a Google Summer of Code program (as student or mentor) you should mention it in your application. Preference will be given to students and mentors participating in the Google Summer of Code or the Outreach Program for Women.
    GSoC students usually get a percentage of their GUADEC expenses covered.
  • If you submitted an abstract to be presented at GUADEC, you should mention it in your application. Preference will be given to people giving presentations at GUADEC.
    The GUADEC paper committee will let the travel committee know which talks have been accepted, so as long as you let us know you submitted one, there is no need to follow up.
  • The Travel committee should reply back about receiving your application within 2-3 days. After that we would accumulate all the sponsorship requests and process them together. So please do not panic (have any butterflies in your stomach) if we take some time to reply on the status. Affirmative/Negative you would surely get a response.
  • No personal emails. Please keep travel-committee Cc’ed on all your replies.

You can find us in the #travel channel at irc.gnome.org.

First Step Complete

Before I could begin doing any of these changes I had one very important step to complete: learning gtk+. In order to do this I basically learnt the essence of gtk+ and then learnt how Glade, a GUI drag and drop program was used. Once that was known all that has to be done is how to import this glade file into C and then manipulate the components that change throughout the program. The link used to understand gtk+: https://live.gnome.org/DocumentationProject/Tasks/DeveloperDocs/BeginnerTutorials

This has beginner's tutorials for gtk in a lot of lanuages. The next step now is to understand all the modules thoroughly based on my new knowledge learned.

__attribute__ ((cleanup)), or how I came to love C again

If your project is written in C, and you don’t mind having a hard dependency on GCC (i.e. you don’t care about building with MSVC++), this GNU C extension does amazing things for your code.

There are other GNU C extensions that are simultaneously useless and crazy, but __attribute__ ((cleanup)) makes up for everything else. For reference, here’s a discussion about using it in GNOME.


Engaging the path to 3.6

Long time no post, I should really have had something up for 3.4.0, and that was of course the plan but on short notice I went to Vientiane, Laos, for $dayjob, the week of the release. Timezone difference, internet connection at the hostel, and a busy schedule made it quite impossible to participate in the release. I didn't stay long but I had a really good time there, thanks again Chanesakhone and Jean Christophe.

a temple in Vientiane

Vientiane, Laos, March 25th 2012

Then, back in Brussels I had to spend time on my new apartement, various administrative tasks, arranging things for gas, electricity and water, keeping an eye on the roof where workers had to knock a chimney down, discussing plans with an architect friend, and so on.

Keys for my new apartment

Keys for my new apartment (and a Collabora bottle opener)

Things finally settled down and two releases have now consecutively been done; 3.4.1 brought some important fixes, and improvements in accessibility, translations and documentation; then last week 3.5 opened the path to 3.6. A new adventure begins…

May 08, 2012

2012-05-08: Tuesday

  • Up, poked mail, worked through license E-mailage, updating the wiki etc. Got idly curious & poked my pile of perl at my Apache OpenOffice (incubating) git repo. Omitting Rob Weir's checkin of everything, hdu's removal of tango and Andrew Rist's changing of header licenses, it's interesting to see out of the ~66k files in the repo, less than 4k have any other changes: 6% of files changed even slightly, filtering just for .[ch]* the same number - 6% - ho hum.
  • It is amusing to me that the "developers from over 21 corporate affiliations" advertised by Apache OpenOffice (incubating), are never enumerated; presumably many are co-incidental employers of free-time volunteers rather than official supporters of the project; and odd given the 23 committers in the last year that Ohloh suggests.
  • Matus got his collaborative editing session going, so we're all set for some Google Summer of Code goodness. Worked away until Lydia & Janice over for dinner.
  • Worked through bugs with patches in the evening, pushing them to people for review, and merging a good few.

Summer of Code, Web 2012 vintage

This year’s Summer of Code has already started, and Epiphany has been lucky enough to get two students assigned. Let’s see who they are and what they’ll be working on.

William Ting, Data Synchronization

William is a last year student of Computer Science at the University of Texas, Austin. He’ll be helping to alleviate a paradigmatic first world problem: I use Epiphany from so many computers that all my data is scattered around and I suffer a permanent pseudo-memory loss condition.

The battle plan is easy. We’ll reuse Firefox’s excellent design for a data sync protocol plus their free-to-use servers (we assume that’s what they were hoping for!), and will integrate the feature right into our browser. Since all the specs and implementation are open GNOME could host in the future a sync.gnome.org instance, but for now we leave that out of the scope of our summer project. Hopefully by 3.6 you’ll be able to optionally enable this functionality, cruise through the web from your tablet, bookmark that hilarious XKCD comic strip, and have it show up in your good old laptop just like that.

I’ll be mentoring this project myself, which was initially proposed by Igalia’s very own Joanmarie Diggs.

Yann Soubeyrand, Anti-phishing Support

Yann is a first year student at the École Nationale Supérieure d’Informatique et Mathématiques Appliquées de Grenoble. His task will be to solve a complicated problem that Epiphany has suffered for a long time: for most users the information provided in the URL entry is not enough to judge whether the page they are visiting is safe. The SSL or certification data is useless for most people, and by showing scary warnings about things they don’t understand at best you’ll train them to just click through to get to the content. To make things worse, most of the time those warnings do not actually indicate someone is trying to scam you, just that apparently setting up web servers correctly is difficult. So all in all, while useful, the information we currently show in the UI is really not that great for the 99% out there.

With this in mind, we’ll try to do the following: using the Google Safebrowsing APIs we’ll try to request authoritative information about the potential “phishiness” of the pages you visit. If we get a warning through this channel we can be confident about there being a security threat, so we’ll show a big, clear message on top of the web content. No jargon about outdated certs or VeriSign trying to take over the planet, just “Listen, our best people tell us this page is almost certainly not safe. Let’s not go there.”. We think this will significantly increase the safety of the browser without violating the user’s privacy, since Google’s API do not require you to disclose the pages you are visiting to validate them (magic? no, science).

Sergio Villar will be mentoring this project.

That’s it, let’s roll

That’s it for now. We’ll make sure to keep you updated about these and other developments in GNOME’s very own web browser. Thanks to GNOME for choosing our proposals, to Google for sponsoring Summer of Code again, and of course to Igalia for its continued support for GNOME and for allowing us to spend our time mentoring the fearless next wave. Happy hacking!

GNOME Design Update, Part One

As always, the GNOME design crew have been hard at work of late. We helped to drive many of the changes you can see in the last GNOME release, including a new color picker, updated application designs, new scrollbars and updated spin button widgets. We haven’t taken our foot off the gas though, and there’s plenty of work to report.

It’s an exciting time in GNOME design land right now. GNOME 3 is a big undertaking: we’re working to improve the entire experience, including everything from interface widgets and controls, through to applications and the core user experience. But we are making good progress, and more and more pieces are slotting into place. Slowly but surely, the design of the overall experience is starting to take shape.

It has been far too long since I’ve posted a GNOME design update. In fact, it’s been so long that I’m dividing this update into two. In this first part, I’m going to detail design work that is focusing on the core GNOME user experience. The second post will cover application design updates, as well as application integration. I’ll post that update in the next few days.

Excitingly, many (though not all) of these new designs are planned as features for the next GNOME release. If you want to help implement any of these designs, just get in touch.

Lock and login screens

This is something that we’ve wanted to do for some time. The lock screen plays much the same role as a screensaver – it is what is displayed when your device is idle. The difference between the lock screen and a screensaver is that the lock screen is really useful, of course, since it will display the time and updates about notifications (the notifications part will also be configurable).

Cue a motion mockup from Jimmac:

This motion mockup shows several things. In the first section, you see the process from boot through to user selection. (Yep, a simple spinner and fade in is all we want.) The second demonstrates what should happen once the machine has gone idle – the screen blanks, is woken up to display the lock screen, then the lock screen is removed and login occurs.

[Edit: a note about this - although the video shows the lock screen being removed with a short mouse drag, it will also be possible to remove it using the keyboard or with the mouse wheel.]

More details about the lock screen design can be found on the lock screen wiki page.

Message tray design updates

One area where we’ve all been keen to see some improvements is around notifications and the message tray. The GNOME design crew recently returned to those designs and came up with some updates which we think will make a big difference.

Under the updated designs, pop-up notifications will avoid the mouse pointer (some of this behaviour already landed in GNOME 3.4, actually) and linger until we are sure they have been noticed. The expanded notifications will also queue up so you can always see when new messages arrive.

Plans are also afoot to replace the moving targets in the tray with larger static icons:

Scrolling

Jon and Jimmac have spent quite a bit of time working through the details of how scrolling should work under different conditions. The idea here is to keep things as consistent as possible across different types of devices, while still leveraging their different strengths.

Jimmac’s motion mockups show the desired behaviour for both pointer and touch devices. We’re hoping to see scrolling improve along these lines in future GNOME releases.

Printing

Jon and Lapo have done a bunch of work that aims to improve the state of printing in GNOME, and they have produced some quite detailed mockups for new print dialogs. These look great in my opinion, and are a huge improvement on what we have right now.

One of the best things about these designs is that they let you get a clear preview of what will be printed. They also present a clear set of simple options.

Initial Setup

Initial setup is intended as a specification for what the user should see the first time they boot into GNOME 3. This is new territory for GNOME, but it is an important piece of the picture if we are going to produce a consistent experience for our users. The goal is to ensure that the system looks and feels like GNOME from the moment someone starts using it.

The initial setup assistant will be an optional component that can serve as a reference implementation for distributions. It includes several important elements for new users, such as a setup screen for online accounts and a product tour to help people get started.

And more…

There are other areas that the GNOME designers have been looking at, but which aren’t as fully developed. Other recent design work on the core user experience includes:

My next post will deal with recent application design work, as well as application integration. See you then. :)


Introducing Pattrn

I’m a COLOURlovers fan. They provide a nice set of simple creative tools that empower a vibrant community to produce awesome design pieces such as patterns, palettes, shapes, colors, etc. It’s a simple yet powerful idea. Inspiring stuff.

I’ve been doing Android-based development for a few months now but I wanted to play a bit more with the platform to get a better grasp on the end-to-end developer experience—from development to distribution. There’s no other way to do that than building an app. This is why I created Pattrn as a weekend project.

Pattrn gives you access to all the patterns created by the COLOURlovers community. You can browse through the latest and most popular patterns and search by keyword or color. You can also keep a list of your favorite patterns and use them as your Android wallpaper. Pattrn is meant to be simple, cute, and snappy.

I’ve just released Pattrn’s first public beta on Google Play. Install it and let me know what you think. I hope you enjoy it!

Video decoding in a sandbox

I would like to explain a bit the stuff I've been working on recently at Igalia. It is about playing with GStreamer and a sandboxing system to try and make the playback of untrusted media more secure. Hopefully writing this will be an occasion for me to get more distance and understand things better, and for others to give me feedback and ideas. Particularly, even though that is for me a field of interest, I do not claim to have any real expertise in security, therefore comments by people who know better would be gladly welcome.

This story started when I decided to have a look at chromium and its internals. It turns out that one very specific aspect of this application is its sandboxing system. In a nutshell, a sandbox is a virtual container in which untrusted programs can be safely run. In the real world, sandboxes are rarely perfect, but they are a significant security improvement over not using one. Chromium uses a sandbox to run its rendering engine (WebKit), which is basically the part that transforms the code of a web page into the graphical representation of it that you see on your screen. The rationale for running WebKit in a sandbox is not that it is untrusted code in itself, but rather that it is a big and complex project that is bound to have bugs, like all big and complex projects. On top of that, the input given to it is quite often data from untrusted sources, which could potentially be forged so that it exploits security bugs to do bad things to your computer and your beloved files. Now, with WebKit running in a sandbox, if a web page has been forged by an attacker to exploit a vulnerability in WebKit, the attacker will only have access to the sandbox environment, which means that it won't be able to do things like access the data on your computer, install software or connect to remote hosts.

As you might know, I like to play with multimedia things, and have hacked quite a bit on or around GStreamer. Therefore, I quite automatically thought of something else that might be worth running in a sandbox: demuxers and decoders. They are relatively big and complex pieces of software to which we regularly pass a whole bunch of untrusted data, would it be in a web context or a more traditional desktop or mobile context.

Fortunately, Julien Tinnes, a developer of the chromium sandbox for GNU/Linux made a stand alone version of it called setuid-sandbox, which can be used by other projects to easily sandbox any process.

Architecture

The way setuid-sandbox works is rather straightforward: there is a sandboxme command that needs to be installed setuid root. You run sandboxme my_command and then from inside my_command, you first set up the file descriptors that you will need (being careful not to put there anything that could allow to escape the sandbox, more on that later), and then you call the provided chrootme() function, which will tell the sandboxme process to restrict the privileges that my_command has (e.g. it can still read and write on the fds that it has open, but it cannot open new ones).

Here is how I organised my integration of setuid-sandbox into GStreamer. What I want to do for now is to put what I think are the "most dangerous" parts (demuxing and decoding) in the sandbox, while letting the other components (mainly source and sinks) outside of the sandbox (for now at least). I decided to create a small program (called gst-decoder) that receives the original muxed and encoded video stream and outputs the decoded video and audio buffers. gst-decoder needs 3 channels of communication with the "controlling" process outside the sandbox (which is called the broker):

  1. one to pass the original stream from the source element in the broker to gst-decoder
  2. one to pass the video buffers from gst-decoder to the video sink element in the broker
  3. one to pass the audio buffers from gst-decoder to the audio sink element in the broker

In the future, more channels for subtitle support or other features could be desirable.

Since I am lazy, I wanted to use off the shelf GStreamer elements to handle these communication channels. For the cases explained above, that would be:

  1. the fdsink element on the broker side, and the fdsrc element in the sandbox
  2. shmsink (in gst-decoder) and shmsrc (in the broker)
  3. same elements as above

Since I expect other people to be equally lazy^W^W^Wwant their life to be made easier, my goal is to try and have this reasonably integrated in GStreamer, and easy to integrate in applications. For that, my best idea so far was to make a sandboxedecodebin element that, from the outside, works like decodebin or decodebin2, at least for simple cases: it has a sink pad that can take any format you would throw at decodebin, and it has an audio and a video source pads that output the decoded result. In the future, it might or might not be a good idea to try to integrate the "sandboxed" functionality in decodebin directly.

I implemented sandboxeddecodebin as a subclass of GstBin, and it has the following flow inside it:

fdsink -> [gst-decoder] | -> shmsrc (video) -> gdpdepay
                        | -> shmsrc (audio) -> gdpdepay

Note that gst-decoder is an external (sandboxed) process, and not a GStreamer element like the other entities of this data flow graph. The sink pad of fdsink and the source pads of the two gdpdepay elements are exported by sandboxeddecodebin through ghost pads, which provides a decodebin-like interface.

The gst-decoder program basically runs a pipeline that looks like that:

fdsrc ! decodebin2 name=decoder
decoder. ! video/x-raw-yuv;video/x-raw-rgb ! gdppay ! shmsink (video)
decoder. ! audio/x-raw-int;audio/x-raw-float ! gdppay ! shmsink (audio)

and it also makes sure to get the privilege dropped at the right time, which is discussed below.

When to drop privileges?

The ordering of operations needs to be thought carefully to combine GStreamer, and these elements in particular, with setuid-sandbox. Each of them brings its own set of conditions.

For setuid-sandbox, inside the sandbox (in gst-decoder):

  • before we call chrootme(): we can open new fds and do a lot of nice initialisation, and we don't want to parse any untrusted data
  • after we call chrootme(): we can't open new fds any more, or do similar initialisation tasks, but we can work on the data we received.

GStreamer has several states in which an element can be, with some rules on what should be done in which state. From the design documentation, the states are defined as follow:

  • NULL: This is the initial state of an element.
  • READY: The element should be prepared to go to PAUSED.
  • PAUSED: The element should be ready to accept and process data. Sink elements however only accept one buffer and then block.
  • PLAYING: The same as PAUSED except for live sources and sinks. Sinks accept and rendering data. Live sources produce data.

In particular, the elements that interest us here behave in the following way:

  • shmsink is responsible for the creation and destruction of the shared memory object and the associated control socket and creates them when going from NULL to READY and destroys them when going from READY to NULL. Since shmsink is used from inside the sandbox, this means that the state change NULL to READY needs to happen before chrootme(). This also means that it won't be able to clean up properly the shared memory object and the control socket.
  • fdsrc doesn't create nor destroy the fd it uses, so that can be done separately. Moreover, in the case of stdin, we leave that responsibility to the system.

And quite obviously, we want gst-decoder to handle buffers only after it has called chrootme(), so that it is ready to run potentially unsafe operations.

This is relatively easy: all we have to do is, in gst-decoder, to call chrootme() once we are in the READY state and before going to PAUSED.

Another issue with the privilege drop is that we use decodebin2 (things would be the same with decodebin), and it only loads the plugins it needs once it knows what kind of data it will have to decode. That is, it needs to load plugins after it has started to analyse potentially unsafe data. My solution to that is to preload all the installed plugins when gst-decoder starts, so that decodebin2 doesn't need any privilege to have access to the plugins it wants (they are already in memory).

This is obviously suboptimal in memory consumption. I can think of two ways to improve that:

  • use a white/black list of plugins to avoid loading plugins we are not likely to need (there are many things we're pretty sure not to need in gst-decoder, such as all sources and sinks or gnonlin)
  • use a separate typefinding sandboxed process that will determine what plugins are needed, then have gst-decoder take as argument the plugins that it needs to load before dropping privileges

Synchronising broker and sandbox

Another synchronisation issue is that the broker has to wait for the sandboxed process to be ready before interacting with it. As seen before, we have 3 channels through which they interact, and they are of two different types:

  • the pipe to which the broker writes, which points to stdin in the sandboxed process
  • the shared memory areas, and their associated control sockets created by the two shmsink

The first one is easy to synchronise: as long as the sandboxed process is not ready, it won't read on the pipe, and fdsink on the broker will just wait until it can write.

The second one is more complex: the shared memory areas are announced over the control socket when they are ready, so this part gets done correctly for free by shmsrc. But the control sockets need to exist when shmsrc tries to connect to them (this happens when going from READY to PAUSED). For now, my workaround is to sleep() for 2 seconds when sandboxeddecodebin goes from NULL to READY, after launching the subprocess. With this, the control sockets are very likely to be created when shmsrc goes from READY to PAUSED.

This is obviously very hackish , and I think I would prefer to use GFileMonitors to check when the sockets are created. Also, I don't know if it's better to do that in sandboxeddecodebin (blocking the switch to READY, but using that file monitoring instead of a sleep(), or going to READY asynchronously if that's possible?) or in shmsrc (in which case I think it should be optional and probably make shmsrc go to PAUSED asynchronously).

Making Preroll work

On the broker side, we have another tricky situation. We typically run a pipeline that contains all of this (the parts between angle brackets are outside of sandboxeddecodebin and given as examples):

<filesrc> ! fdsink (passes data to gst-decoder)
shmsrc (gets data from gst-decoder) ! gdpdepay ! <autoaudiosink>
shmsrc (gets data from gst-decoder) ! gdpdepay ! <autovideosink>

This pipeline is atypical in that it has a sink that is not really at the downstream end of it (fdsink, which sandboxeddecodebin uses to pass data to gst-decoder). Data would go through it, then through gst-decoder and its own pipeline, and then emerge back in the broker's pipeline in the shmsrc elements.

This is a problem at the preroll phase. Preroll is what usually happens when going to PAUSED: the sinks wait until they have a buffer to render before committing the state to PAUSED. The issue with our pipeline, is that the "real" sinks will only get the data they need to commit to the PAUSED state if fdsink lets the data through, but fdsink only passes data once it is in PLAYING state (apart maybe from one initial buffer). On top of that sandboxeddecodebin is a subclass of GstBin. By default, GstBin only changes to the next state (e.g. PLAYING) once all its elements have reached the previous one (e.g. PAUSED). This gives us a nice deadlock: the final (downstream) sinks are waiting for data to come to them to commit their change to PAUSED, GstBin is waiting for all its elements (including final sinks) to finish their transition to PAUSED before asking them to go to PLAYING, and fdsink is waiting to be asked to switch to PLAYING before it lets the data through (that the final sinks are waiting on). My workaround to solve this deadlock is to manually request fdsink to go to PLAYING when sandboxeddecodebin is switching to PAUSED. That way, fdsink is "one state ahead" of the rest, and lets the data go through. I haven't decided yet if it's a very ugly way of solving that issue or if it's an awesome clever hack. If you have an idea of a cleaner solution, feel free to suggest it in the comments!

Analysis of open file descriptors

Once the privileges have been dropped, the sandboxed process is very limited in what it can do, but it still can use all the fds that it has open, which might be a way for it to escape the limitations we want to put on it. For instance, imagine that the sandboxed process has an open fd on the device that contains your home directory (say, /dev/sda). By reading it, it can access all your data, even though the sandbox is designed not to let it open more files.

This precise example is very unlikely to happen in our case, but some less obvious fds could lead to ways to escape the sandbox. That is why I think it is necessary to analyse the file descriptors that are open in the sandboxed process and to try to understand the risks they bring.

I took a "snapshot" of the open fds of gst-decoder while it was decoding a video, and here is what it looks like:

guijemont@thirtytwo:~$ ls -lv /proc/5860/fd
total 0
lr-x------ 1 guijemont guijemont 64 2012-04-18 18:17 0 -> pipe:[8348338]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 1 -> /dev/pts/5
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 2 -> /dev/pts/5
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 3 -> anon_inode:[eventfd]
lr-x------ 1 guijemont guijemont 64 2012-04-18 18:17 4 -> pipe:[8348342]
l-wx------ 1 guijemont guijemont 64 2012-04-18 18:17 5 -> pipe:[8348342]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 6 -> socket:[8358884]
lr-x------ 1 guijemont guijemont 64 2012-04-18 18:17 7 -> pipe:[8359036]
l-wx------ 1 guijemont guijemont 64 2012-04-18 18:17 8 -> pipe:[8359036]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 9 -> anon_inode:[timerfd]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 10 -> /run/shm/shmpipe. 5860.    0
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 11 -> socket:[8358886]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 12 -> socket:[8358887]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 13 -> socket:[8358888]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 14 -> /run/shm/shmpipe. 5860.    1
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 15 -> socket:[8358890]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 16 -> socket:[8358891]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 17 -> socket:[8358892]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 18 -> socket:[8358893]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 19 -> socket:[8358894]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 20 -> socket:[8358895]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 21 -> socket:[8348346]
lrwx------ 1 guijemont guijemont 64 2012-04-18 18:17 22 -> socket:[8348347]

I used the "usual suspects" (strace and gdb) to look further into this and understand where each fd comes from, and try to get an idea of how necessary it is and of how much of a risk it brings.

  • O: that is stdin, and it is the pipe I create when starting sandboxme gst-decoder. Also, it is read only. I don't think an attacker could do much with this, and we need it anyway.
  • 1 and 2: stdout and stderr, plugged to the pseudo tty where my test gst-launch command was running. This is clearly not necessary, and could be exploited for privilege escalation if there's a bad bug somewhere in devpts. I modified the code to make stdout and stderr point to /dev/null instead when gst-decoder is launched. There is an environment variable that can prevent that from happening when one wants to see the debug messages that are output by gst-decoder.
  • 3: This is an event fd used by the GMainContext. I suspect that at least a few of the components we run to decode our stuff needs a GMainLoop, and therefore a GMainContext. And I don't think this is very dangerous, though I don't know much about the complexity and safety of the event system.
  • 4 and 5: this is a pipe used by the GLib unix signal code. Both ends of the pipe are inside the sandbox, so I don't think this would be much of a problem.
  • 6 and 21: shm area control socket for audio. There is one fd created by socket() that is bound to the right temporary file, then another fd is created by accept() when the broker connects. We definitely need that if we want to use shm, which I think we do for performance reasons (I did not run benchmarks though).
  • 7 and 8: pipe open by some code in /usr/lib/frei0r-1/facedetect.so when it is g_module_open()'ed. I don't think we need that at all, and it might be a good motivation to try and not load all plugins. A limited risk though, since both ends of the pipe are inside the sandbox.
  • 9: a timer fd opened in the same conditions as the pipe of fds 7 and 8 (by frei0r's facedetect). This one definitely looks like an unnecessary risk, though I don't know how much of a risk it actually is.
  • 10 and 14: these are the shared memory areas (one for audio, one for video), so I think we definitely want them. The alternative would be to use regular sockets instead to pass the buffers, but I fear it might cost us much in performances for little added security, though this issue could deserve more investigation.
  • 11, 12, 15, 16, 17, 18, 19 and 20: these 8 fds are actually 4 socket pairs, with each time both ends inside the sandbox. They are all created by gst_poll_new(), by the following pieces of code:
    • shmsink in gst_shm_sink_start(). It does that twice: once for audio, once for video.
    • fdsrc in gst_fd_src_start().
    • the system clock (in gst_system_clock_init(), via gst_poll_new_timer()).
  • 13 and 22: shm area control socket for video. There is one fd created by socket() that is bound to the right temporary file, then another fd is created by accept() when the broker connects. We definitely need that if we want to use shm, which I think we do for performance reasons (I did not run benchmarks though).

Play with it!

You can check out the code from its github repository, instructions are available here.

Being accepted in GSoC and revamp of pessulus

Recently I was accepted in Google Summer of Code program and my task is to revamp pessulus lockdown editor, to bring it up to date (dconf, GTK+3, etc.).

In short, the plan is to make an lockdown editor, that is easier to use than dconf-editor with common configuration presets.  The work is not only to make gsettings more accessible, but also to implement new lockdown features, if necessary.

In my next blog post I will publish list of lockdown features that the new pessulus incarnation should support, list of lockdown scenarios and default settings for those scenarios.

My projects wiki stub has some basic information. My nickname in IRC is Tranzistors and if you are interested in locking down computers, feel free to contact me.


May 07, 2012

Expecting an interesting summer

Hi all,

I’ve been accepted as a Google Summer of Code 2012 participant to work on the proposed project titled “Support for Gamepad API in WebKitGTK+ and general gamepad configuration options in System Settings” (abstract on google-melange.com). The wiki page for the project will be located here. The project will cover three notable additions to GNOME-related projects:

  • Gamepad API specification support for the GTK+ port of the WebKit rendering engine
  • Gaming devices panel in the GNOME Control Center for advanced gamepad and joystick configuration
  • Plugin in GNOME Settings Daemon to load configuration for previously configured devices when they’re connected

My mentor will be Carlos Garcia Campos.

Looking forward to a productive summer!


First week working on GNOME-Boxes' port was awesome!


Last week I spent some time to familiarize myself with the code and start the port itself, as planned in sprint00 and sprint11 respectively.

After some days reading the code (yeah, I'm not a good reader), I finally understood Daniel P. Berrange's idea for install-scripts (libosinfo) and put my hands on the code, starting the port (or, at least, trying).
In this process, 4 small patches were produced and sent to libosinfo's mailing list (waiting for review), and I'll consider sprint0 finished and go to sprint1, doing this a big sprint with almost 3 weeks, as soon as patches are accepted.

See ya!



0sprint0: Familiarize with the code/project/mentor
deliverable: a simple patch related to the project


1sprint1: Porting Boxes to new API
deliverable: Boxes using new automated installation API of libosinfo and dropping all OS-specific automation code

May 06, 2012

PyGObject 3.3.1 released

This announcement comes very late (a week after release), but better late than never..

The first PyGObject 3.3 series release is now out, with lots of yummy fixes and improvements. Dieter, Sebastian, and I went through a round of bugzilla spring cleaning to clean up old bugs, fix simple bugs, and apply good patches that were waiting, so as a result the patch queue is now almost empty and PyGObject works better than ever.

There was also quite some work on the test suite: it became a lot stricter and robust, and now also enforces PEP8 compatibility and absence of pyflake errors of the code.

One small but handy new feature is that the freeze_notify() and handler_block() methods are now context managers, i. e. they automatically call the corresponding thaw_notify()/handler_unblock() at the end of the with statement in an exception-safe way. ((#672324)

There are almost no API changes in this release, so it should work fine with GNOME 3.4 and applications developed with pygobject 3.2. The one exception is the removal of the Gobject.get_data() and Gobject.set_data() methods. They were prone to errors and crashes as they are not safely bindable, and in Python you can and should just use normal Python object attributes instead.

Complete list of changes:

  • GSettings: allow extra keyword arguments (Giovanni Campagna) (#675105)
  • pygtkcompat: Correct Userlist module use (Jose Rostagno) (#675084)
  • Add release-news make rule (Martin Pitt)
  • Add “make check.nemiver” target (Martin Pitt)
  • Test flags and enums in GHash values (Martin Pitt) (#637466)
  • tests: Activate test_hash_in and apply workaround (Martin Pitt) (#666636)
  • Add special case for Gdk.Atom array entries from Python (Martin Pitt) (#661709)
  • test_gdbus: Call GetConnectionUnixProcessID() with correct signature (Martin Pitt) (#667954)
  • Add test case for Gtk.ListStore custom sort (Martin Pitt) (#674475)
  • GTK overrides: Add missing keyword arguments (Martin Pitt) (#660018)
  • Add missing override for TreeModel.iter_previous() (Martin Pitt) (#660018)
  • pygi-convert.py: Drop obsolete drag method conversions (Martin Pitt) (#652860)
  • tests: Replace deprecated assertEquals() with assertEqual() (Martin Pitt)
  • Plug tiny leak in constant_info_get_value (Paolo Borelli) (#642754)
  • Fix len_arg_index for array arguments (Bastian Winkler) (#674271)
  • Support defining GType properties from Python (Martin Pitt) (#674351)
  • Handle GType properties correctly (Bastian Winkler) (#674351)
  • Add missing GObject.TYPE_GTYPE (Martin Pitt)
  • Fix test_mainloop.py for Python 3 (Martin Pitt)
  • Make callback exception propagation test stricter (Martin Pitt) (#616279)
  • Add context management to freeze_notify() and handler_block(). (Simon Feltman) (#672324)
  • Add support for GFlags properties (Martin Pitt) (#620943)
  • Wrap GLib.Source.is_destroyed() method (Martin Pitt) (#524719)
  • Fix error message when trying to override a non-GI class (Martin Pitt) (#646667)
  • Fix segfault when accessing __grefcount__ before creating the GObject (Steve Frécinaux) (#640434)
  • Do not bind gobject_get_data() and gobject_set_data() (Steve Frécinaux) (#641944)
  • Add test case for multiple GLib.MainLoop instances (Martin Pitt) (#663068)
  • Add a ccallback type which is used to invoke callbacks passed to a vfunc (John (J5) Palmieri) (#644926)
  • Regression test: marshalling GValues in GHashTable (Alberto Mardegan) (#668903)
  • Update .gitignore (Martin Pitt)
  • Fix “distcheck” and tests with out-of-tree builds (Martin Pitt)
  • Add a pep8 check to the makefile (Johan Dahlin) (#672627)
  • PEP8 whitespace fixes (Johan Dahlin) (#672627)
  • PEP8: Remove trailing ; (Johan Dahlin) (#672627)
  • tests: Replace deprecated Python API (Martin Pitt)
  • Fail tests if they use or encounter deprecations (Martin Pitt)
  • Do not run tests in two phases any more (Martin Pitt)
  • test_overrides: Find local gsettings schema with current glib (Martin Pitt)
  • Add GtkComboBoxEntry compatibility (Paolo Borelli) (#672589)
  • Correct review comments from Martin (Johan Dahlin) (#672578)
  • Correct pyflakes warnings/errors (Johan Dahlin) (#672578)
  • Make tests fail on CRITICAL logs, too, and apply to all tests (Martin Pitt)
  • Support marshalling GI_TYPE_TAG_INTERFACE (Alberto Mardegan) (#668903)
  • Fix warnings on None values in added tree/list store rows (Martin Pitt) (#672463)
  • pygtkcompat test: Properly clean up PixbufLoader (Martin Pitt)

Hello, Planet GNOME. Hello, CHI2012.

My blog has just been added to Planet GNOME, so let this post be my way to say that I am very happy to join the fine people there (including several colleagues at Igalia).

This week I will be attending the CHI2012 conference in Austin, TX.  This is the main conference on human-computer interaction and UX design. I will write a long recap once it is over, with special attention to those bits that may be interesting to GNOME and other work that we are carrying out at Igalia, and also to things that are just too wonderful, eye-catching or plain weird to miss.

Google Summer of Code 2012

I’m accepted with my proposal on Google Summer of Code for this year. My mission is to bring clang magic to Anjuta. “Anjuta? What is Anjuta?”, maybe you wonder yourself now. Anjuta is a IDE just like Eclipse.

Clang is a compiler front-end for the LLVM compiler. With this compiler front-end for C, C++, Objective C and Objective C++ code we can get better results in Anjuta. For example if you make a simple mistake by writing code Anjuta will warn you. This can save a lot worse.

The first major obstacle is to make thoughts about the future architecture of the language support interface, so that you’ll be simple load plugins for a language feature like autocompletion or indentation. To support this purposes I’ll split up already available language plugins in an indentation part and the support part.

May 04, 2012

Sketching Butaca: IMDB on a tablet

Butaca is an application for the N9 developed by Simon Pena, hacker at Igalia. It is meant to be a companion to film lovers, providing information about movies, actors, directors… and even showtimes near you. It uses The Movie Database and Google Showtimes as backends.

As a design exercise, I started thinking some time ago about how we could port Butaca to a tablet form factor. As usual, this was the tool selected to help my thinking and get started in the design:

Notebook and pen

My basic idea was to keep the current presentation in pages, replacing the Back button with a horizontal navigation that would let you move back and forth along your history. The pages that you have seen are on your left; the “forward” ones are to the right, along with shortcuts to launch each of the main sections of the application.

To illustrate this, I drew a few mockups with Inkscape. This is one of them:

Butacka mockup

This helped in visualizing the solution, but important questions had not been quite answered yet. Would this idea really work on a tablet? Would it look nice? Does it really make sense to structure navigation history in this way? I might have tried to build a functional prototype, but prototypes are used to confirm decisions rather than raise questions. It is important to avoid committing too soon to a particular design, before the space of possible solutions has been fully explored. What was needed at this stage was something else, something tentative and exploratory. What was needed was a sketch.

Sketches are cheap, disposable, quick. So, I took a bunch of screenshots of the N9 application and joined them together with just ~160 lines of QML, in a sort of interactive collage. This method would work just as well with nice ad-hoc mockups, but those take more time and the point was to keep it quick. Igalia had provided me with a WeTab running GNOME 3, so I just had to load my little application on it and take the following video:

(direct link to video in Vimeo; sorry for the quality, the WeTab’s screen is terribly reflective)

Now, that is a better way to get the point across, isn’t it?

The take-home lesson here is that trying out ideas is important. There are techniques that assist us in creating interactive sketches quickly, which can be very useful when we need to explore ideas and build on them to generate new ones. Furthermore, a sketch can be a great communication tool, as I hope to have shown with the preceeding video.

Translating documentation in Google Code In program

Half a year ago the annual Google Code In contest was held. And, thanks to Andre Klapper’s enthusiasm, the GNOME Latvian localization team chose to participate and provide 20 translation tasks for secondary school students. Although the contest itself ended in January, we finished our part of the work only a few weeks ago, in time for the release of GNOME 3.4.1. This blog post describes how it went and what we learned.

Preparation

Since we need people with knowledge of English and Latvian (a small language), we knew hardly anyone could help us if we didn’t spread the word. To do this, we contacted the national ICT teachers’ organisation and sent them digital leaflets to give to their students. The leaflets contained information about the Code In program itself and only a slight nudge toward tasks specific to Latvian. This worked quite well, and we attracted a decent amount of interest, with six pupils actually completing our tasks.

We chose documentation for the tasks because it should be understandable for a layperson. Arguably, translating Inkscape or the like would be more useful, but UI strings are much harder to tackle without prior experience. Our estimate of the time to translate 50 strings was one day (an “after school” day, not a full 8-hour workday). For the first round, we prepared five tasks, which looked something like this:

Translate into Latvian the Gnome Desktop Help chapters about Shell (strings from 1994 to 2231). It consists of approximately 500 sentences. You can take a look at the rendered English version here. General information on translating GNOME can be found here.

First wave

After the first few exchanges we found out that absolute beginners need a lot of hand-holding. Worst of all, they were afraid to ask for advice. So there were a few misunderstandings and unneeded stress. Having learned from this, we added some tips, which had been obvious to us, but not to the pupils:

  • Translating is easier with specialised tools, such as poEdit or Lokalize.
  • A spelling check is always a good idea.
  • User interface translations can and should be taken from the corresponding UI .po file.

We also learned that phrasing a task like “go take that file over there and translate strings X through Y” doesn’t work, because the master branch is a moving target, not all editors have string numbering, and pupils don’t ask for assistance. To solve this, we sliced[1] larger .po files into task sized bites and hosted them on our own FTP server.

For quality control, we checked a handful of random strings for common issues, and if the translations were good enough, the work was accepted. In a couple of cases, we did request improvements, which the students then made quite promptly.

So, five pupils completed five tasks, and we started preparing for the next round. This time we thought 15 tasks would be enough. We weren’t quite right.

Second wave

Not all pupils from the first round stayed, but those who did seemed very efficient (e.g., finishing a four-day task in a single day). At first this made us concerned about quality, but our usual random sampling showed no significant issues. In the end, all 15 tasks were completed in less than two weeks, much sooner than planned, so we had clearly underestimated our participants.

Review and editing

For best results, all translations should be reviewed, and first-time translations must be. We did expect to do extra work at this stage, but in hindsight, much of it could have been avoided. Lessons learned from the editing process:

  • More communication with the participants would have helped a lot. Google’s Melange system discourages personal communication, but having an IRC room would have let us resolve some issues much earlier.
  • Provide some style guidelines and a list of common mistakes as required reading. Fixing such subtle problems afterwards can be time consuming.
  • Inexperienced translators tend to translate word-for-word, forgetting that grammar and phrasing differ between English and the target language.
  • Before being given a full task, the participant should translate a small test file with common pitfalls, and the mentor should give detailed feedback. Simply making pupils aware of the issues increases their performance significantly.
  • Did I mention the need for communication?

Conclusions

The overall result is positive — the documentation for Latvian language is finally finished and shipped for distributions that use Gnome 3.4.1. One of the students expressed interest in continuing translation work. We hope all the other participants enjoyed the process as well.

—-

[1] To convert a 600 string file into three files of 200 strings each, make three copies of the original file. Open each one with a text editor and delete the unneeded strings, but keep the header information. When the translations are done, paste or merge the .po files in one. Don’t forget to manually combine the copyright information from .po headers and the “translator-credits” string, if there is one.


FOSDEM 2012 – can beer freeze?

Thanks to my awesome employer Igalia, I am flying tomorrow to the cold city of Brussels to attend FOSDEM 2012.

I'm going to FOSDEM, the Free and Open Source Software Developers' European Meeting

I will give a lightning talk, Saturday at 13:40, about my balloon adventures at Nowhere, with an emphasis on how Free Software made it possible. Hopefully, this will motivate other Free Software hackers to get out of their basement and hack in the “real” world :).
The talk should be streamed live at this url (in the Ferrer room).

Many other Igalians will come (I think there will be 14 of us), and will give talks.

First bug fix

My first bug fix and also my first contribution to GNOME.

Reported a Bug : The virtual keyboard nor the options (i.e. help, home, etc) were visible in the hangman activity. It did not take inputs from the real keyboard either. Only the black board was visible along with tux at the side. Esc button had to be used to exit the activity.

A TypeError would only be encountered when running it in default locale. On selecting a language this problem would not persist.

By using error handling in hangman.py GCompris was falling back to English. I made the following changes in /usr/local/share/gcompris/python/hangman.py:

#Get the name of the language for the current locale
try:
 self.language=gcompris.gcompris_gettext(gcompris.get_locale_name(gcompris.get_locale()))
 self.wordlist=gcompris.get_wordlist("wordsgame?default-$LOCALE.xml")
#Fallback to English
except(TypeError):
 self.wordlist=gcompris.get_wordlist("wordsgame?default-en.xml")
 self.language=_("English")

I was helped by Bruno Coudoin.

GSoC 2012!

I don't think words are enough to express my happiness for being selected for the Google Summer of Code this year. I am so glad to now be part of the GNOME community. I can't thank my mentor Bruno Coudoin enough for guiding and helping me throughout the entire application process. I'll be creating interactive activities focusing on the science and miscellaneous section of GCompris. The project would include two activities theming space, a food related activity and one environment related activity.

Really looking forward to this summer of coding and fun!    

Also, felt so nice to see my name up here :



Culling of the Fold

I’ve received a bunch of questions about the state of the perl-Clutter bindings in the past couple of years; I entertained a vain hope of returning to actively maintaining them, but the effort of actually maintaining the underlying C library left little to no time for bindings (just ask the pyclutter users).

luckily, the stellar work done by Torsten Schönfeld on Glib::Object::Introspection allowed me to jump start an introspection-based binding module for Clutter in about half an hour – including the time spent porting one of the examples in the C API reference to Perl.

perl-Clutter is in git.gnome.org, and it works pretty much like perl-Gtk3 — same Dist::Zilla based setup, same dependencies.

contributions are very much welcome — though I’ll try to reserve some spare time for going back to the same levels of compatibility as the old, static bindings. one area for new contributors is pure-Perl overrides to paper over the C API; another is writing Cogl bindings, possibly static ones like perl-Cairo, as the Cogl API is not very introspection-friendly.

May 03, 2012

Going to JSConf.eu 2011

Back in 2009 I had the chance to attend the european edition of the Javascript Conference for the first time. It was a nice and intense learning experience (it runs only for two fully packed days). This event is the counterpart of the US edition however it gathers a wide and heterogeneous Javascript community from around the world and not just Europe.

And guess what, after missing my ticket last year, I’m attending again this year’s edition sponsored by igalia. I will be giving a talk titled “Javascript, the GNOME way” in which I will discuss the relationship between GNOME 3 and Javascript, the technologies behind it and how to get started writing JS in the “GNOME way”. My goals with this presentation are 1) to communicate to the wider Javascript audience about the awesomeness of using the GNOME libraries in JS and 2) to try bridging the two communities in subjects that matters to both, to ultimately foster collaboration and alignment between them.

I’m sure this year edition will be as cool as the others, and I look forward to absorb again all that knowledge, ideas, enthusiasm and yeah, the Berlin’s autumn breeze too.

See you there.

Vagalume port to Moblin2

During summer, I started to work on porting Vagalume UI to Moblin platform during my beloved hackfest hours. Vagalume is a Last.fm client for GNOME and Maemo, created by Alberto García (aka Berto). Moblin is an open source project impulsed by Intel, to create a GNU/Linux-based platform optimized for mobile devices (mainly, those powered by Intel’s Atom processor and graphics accelerator).

Vagalume’s UI is currently based on GTK+ for GNOME and Hildon for Maemo. However, Moblin user-experience is based on Nbtk and Clutter, yet it can run pure GTK+ applications. Taking a look at Nbtk toolkit was in my wishlist since it’s presentation at GCDS 2009, where some cool features of the project attracted my interest, like using CSS for styling widgets. About Clutter… well, it’s a project I personally like a lot and have been following since early versions. Motivation was ready and served.

The goal

The porting main goal is to get Vagalume running in Moblin2, sharing the platform’s look n’ feel. Revamping the UI was not just replacing widgets, but initially make Vagalume use the technologies present in a Moblin ecosystem, and “by-the-port”, perform a complete redesign of the UI, getting help from those talented designers at Moblin team.

So far…

After some weeks of hacking and festing, we have partially completed the toolkit migration, and developed a concept-proof UI redesign for the main window using Nbtk and custom Clutter widgets, except for the shell-menu which was not migrated yet . A screen-cast demo of the new UI is available. Notice that the target at this stage was not to align with Moblin’s look n’ feel, but just mixing differnt toolkits and get them to run together.

One of the new features we thought it would be interesting to include is to provide information of next and prevoius tracks, right in the main UI. The Last.fm API provides means to fetch playlist items in advance, so was not really difficult to implement that (with some core patches from Berto.. thanks).

The port’s source code is temporarily in a public repository at Gitorious.org in the moblin branch, but it will eventually get merged upstream when it gets mature enough. To build the branch, you will need a Moblin library-featured environment, like the SDK provided, or the Moblin platform itself installing the development tools and libraries. Alternatively, you can use my jhbuild moduleset.

There are some issues when building the project:

  • Running Nbtk in 64 bits platform drops a segfault due to a problem in libccss-0.3.1, so use 32 bits for hacking by now.
  • Moblin platform is not properly detected during autogen.sh stage, so you have to pass ‘–with-platform=moblin2′. This shall be fixed soon.

What’s next

Right now, we are trying to get support and feedback from Moblin UI designers, in order to plan a complete layout and style redesign. Making Vagalume UI consistent with Moblin environment is the current milestone. In the mean, we are doing several stability tests and improving toolkit integration.

Contributions are very appreciated, specially with design ideas, testing and project build integration. I can even review patches in my limited time.

Stay tuned.

LibreOffice Data And Notes, Let The Computer Do The Tedious

We have been live on LibreOffice now for a few days and things are going well.  In conversations with our support group, the biggest issue that people had was "file location".  Most people have no idea where their documents are saved.  If they customized MyDocuments location or lost any RecentDocuments entries they struggle and assume that everything was lost in the upgrade.  File management still continues to be the biggest problem for users, and it's not ever going to change.  I believe that devices like iPhone and iPad succeed because there is no "file system".  Save a photo, and it's available to all applications.  Users don't have to make any choices in that regard; no file names or folders.  That's why the desktop has been customized to allow for as much drop and drag as possible.

Here is a shot of top running with about 100 open LibreOffice instances.  Looks like we could easily get another 100-200 instances running easily, which is wonderful.  Typing is crisp and fast.


While watching the LibreOffice server run and doing some slight tuning, I have been able to hack in some features that I wanted to merge into our "Support Portal" software.  This software is accumulating and monitoring nearly every click and issue on the GNOME desktop and application servers.  One of my pet peeves about software is when there is a tedious task that the computer can and should do for you and the software requires that you do it manually.  Much of the information we are logging is informational, but some of it is "actionable".  These are things that require a fix or step in order for the users issue/request to be resolved.  So I have begun to develop the [ Summary ] tab.  This section monitors all data that is coming in from various software packages and creates an easily seen tile/button of information.  Someone watching the portal is instantly aware of something that they need to do and it's easy for them to find the offending server or application. 

I know there are people out there that create UI fulltime and I'm sure these rough screens are hard to view.  :) But at this point this is more about fleshing out ideas and trying to create something useful for our staff.  Time does not allow for fulltime software engineering, this is usually hacked along with many other projects concurrently.

The screen is broken into 18 tiles and the last 18 events that require our attention appear.  The following items have been marked as "actionable" (more to come):

* RSH failure, whereby user is trying to run software and they don't have the right permissions
* CALENDAR failure, Evolution has a bug where if it crashes it occasionally drops their Groupwise calendar.  The user therefore does not get alarms for meetings because the calendar is disconnected.  We get about 1-2 of these a week
* MEDIA request, where users have asked us to send them our open source DVD which contains the software we run at the City for them to take home for Windows/Mac personal computers.
* FORCEQUIT - Networking, which means they logged back into the server and indicated they dropped off the server.  This usually is a cable or jack problem
* FORCEQUIT - Electrical, which means the power dipped and they were kicked off.  This means that the users UPS is probably dead, or they are not plugged into the battery side.  All of our employees have a UPS; if you have been to Florida in the summer you know why.
* LOAD, one of the servers has gone over 10% CPU usage, this very often means an errant process
* PRINT, there are print jobs that have not flushed from one of the servers within a 15 minute period.  This usually means paper jam, out of toner, etc.  Support can connect to the printers with a browser and debug what's happening.

When you hover your mouse over the button tile, it indicates which tab contains more detailed information and also provides a FIX which normally resolves the issue.  Clicking on the button brings up a user detail screen.


This new area is underdeveloped, but I'm looking forward to continued progress and testing.  I'm also looking forward to NX client for iPad 3 which will allow us to carry this information around at all times.

GStreamer backend for video in Firefox

Good news to hear that the GStreamer backend for video playback in Firefox has landed, due to a flurry of work by Alessandro Decina in the last few months.  Of course, this isn’t part of the standard Firefox build (but maybe some day?), but it’s very useful for putting Firefox on mobile and embedded platforms, since GStreamer has a well-established ecosystem of vendor-provided plugins for hardware decoding.

OggStreamer: audio capture and streaming device

Recently learned about a cool new open hardware project called OggStreamer.  They’re designing and making a small device that records an analog audio signal and streams it using Ogg/Vorbis.  It’s an open hardware project, so all the schematics and PCB layout is provided.

Boot & Base OS Miniconf at Linux Plumbers Conference 2012, San Diego

Linux Plumbers Conference Logo

We are working on putting together a miniconf on the topic of Boot & Base OS for the Linux Plumbers Conference 2012 in San Diego (Aug 29-31). And we need your submission!

Are you working on some exciting project related to Boot and Base OS and would like to present your work? Then please submit something following these guidelines, but please CC Kay Sievers and Lennart Poettering.

I hope that at this point the Linux Plumbers Conference needs little introduction, so I will spare any further prose on how great and useful and the best conference ever it is for everybody who works on the plumbing layer of Linux. However, there's one conference that will be co-located with LPC that is still little known, because it happens for the first time: The C Conference, organized by Brandon Philips and friends. It covers all things C, and they are still looking for more topics, in a reverse CFP. Please consider submitting a proposal and registering to the conference!

C Conference Logo

Finished migration

I can say the migration is finished. There’s till my blog on line Wordpress.com but that could be left for later. I think on putting a redirect there, or just taking it down.

The thing is that octopress is a pretty comfortable scheme. It allows me to write and sanitize my blog at home, or wherever I have my laptop, no matter if I’m online or not. The point is I can do a bunch of stuff in my pc without internet connection, which is a very rare affair in under-developed countries.

There’s still stuff missing, and I’ll try to add it on the way. I would like update my twitter stream with my posts automatically from rake deploy task, but since Twitter now uses OAuth, that became a mess, and I don’t understand OAuth scheme yet, so I’ll have to let it be for a while. I was concern at first for my spelling, but now anymore, my vim has spell checking, and after change rake new_post task to launch vim with spell checking set on, it’s way better than Wordpress correction system.

So, as you can see, so far so good, I like this pretty much, and think is easier and better than Wordpress. I encourage you people to join.

Initial Commit

As you can see, the migration to octopress started with the right foot. The blog is up and running, and I just have to try three times. That was an easy one. The first time I installed gentoo, took me about ten times to get it right.

I had some help, some guy named zanshin in #octopress at freenode, and the docs at Octopress.org. Now I’ve installed a new theme, added my tweets stream, and I’m on the way to migrate my content from the previous wordpress blog. I have found a tool named exitwp in some post of another guy in the same situation, and will test it soon.

You know what’s missing ? You probably have see all those sites where you make an account for yourself, and they ask you for an URL, like your site. Well, I’ve been putting the wordpress site there. My bad, that should be set on a central place, now I have to go changing that address everywhere. Maybe I should make a redirect page in the wordpress blog, although I have to say, I’ve never had too many readers.

Ohh, there’s other stuff missing, one that I probably miss a lot. wordpress.com have a spell checking utility, well, octopress hasn’t one. It’s up to my vim, and I’m pretty lazy. Since english isn’t my mother tongue. I’ll have to look out for error and typos.

Getting the ICC display profile

I’m at LGM this year, and so far it’s rocking pretty hard. The number one question people have asked is “how do I get the screen profile for a window“. I figured this should be easy to get using colord, and then spent a few minutes working on some proof-of-concept code. This ballooned into a couple of hours doing it properly asynchronously and making it work correctly on multihead, and the result was a few hundred lines of complicated code with quite a few exit points. I don’t want people to add 300 lines of boilerplate to their project just to map a GtkWindow to a .icc filename.

So I’m now shipping an additional optional colord-gtk helper library in colord that allow you to use one async function to get the profile a given widget should use. There’s a demo available here.

The alternative is of course to read the X11 _ICC_PROFILE atom, but that does not support multi-head, and really won’t work when we move to Wayland. It’s also not a lot of fun grabbing lots of binary data from the xserver in a GUI program. In the long term future we’ll be doing full screen color management in shaders, with full toolkit support using Wayland, but that’s a few years from being reality. If you’ve got any ideas or have comments about the API, let us know on the mailing list. Thanks.

May 02, 2012

Social Security vs. Private Retirement

"Now my adopted state has chosen to turn its back on its tradition of welcoming immigrants, and of..."

““Now my adopted state has chosen to turn its back on its tradition of welcoming immigrants, and of tolerance and freedom to all its citizens, with a proposed amendment to the NC State Constitution no less, that hangs a great banner across the entrances to the state saying to a whole bunch of American citizens: You are not welcome here.””

- Bob Young

Anatomy of a Fedora 17 ISO image

My spare time has been limited lately, so progress on producing Mac-bootable Fedora install images has been a bit slow. Thankfully it looks like everything's gong to land in time for Fedora 17[1] so hurrah for that - all that's missing right now are the last couple of patches that make sure the boot picker displays useful labels on the drives.

So how is this accomplished? Here's a hex dump of the first few K of the image.
00000000  45 52 08 00 00 00 90 90  00 00 00 00 00 00 00 00  |ER..............|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  33 ed fa 8e d5 bc 00 7c  fb fc 66 31 db 66 31 c9  |3......|..f1.f1.|
00000030  66 53 66 51 06 57 8e dd  8e c5 52 be 00 7c bf 00  |fSfQ.W....R..|..|
00000040  06 b9 00 01 f3 a5 ea 4b  06 00 00 52 b4 41 bb aa  |.......K...R.A..|
00000050  55 31 c9 30 f6 f9 cd 13  72 16 81 fb 55 aa 75 10  |U1.0....r...U.u.|
00000060  83 e1 01 74 0b 66 c7 06  f1 06 b4 42 eb 15 eb 00  |...t.f.....B....|
00000070  5a 51 b4 08 cd 13 83 e1  3f 5b 51 0f b6 c6 40 50  |ZQ......?[Q...@P|
00000080  f7 e1 53 52 50 bb 00 7c  b9 04 00 66 a1 b0 07 e8  |..SRP..|...f....|
00000090  44 00 0f 82 80 00 66 40  80 c7 02 e2 f2 66 81 3e  |D.....f@.....f.>|
000000a0  40 7c fb c0 78 70 75 09  fa bc ec 7b ea 44 7c 00  |@|..xpu....{.D|.|
000000b0  00 e8 83 00 69 73 6f 6c  69 6e 75 78 2e 62 69 6e  |....isolinux.bin|
000000c0  20 6d 69 73 73 69 6e 67  20 6f 72 20 63 6f 72 72  | missing or corr|
000000d0  75 70 74 2e 0d 0a 66 60  66 31 d2 66 03 06 f8 7b  |upt...f`f1.f...{|
000000e0  66 13 16 fc 7b 66 52 66  50 06 53 6a 01 6a 10 89  |f...{fRfP.Sj.j..|
000000f0  e6 66 f7 36 e8 7b c0 e4  06 88 e1 88 c5 92 f6 36  |.f.6.{.........6|
00000100  ee 7b 88 c6 08 e1 41 b8  01 02 8a 16 f2 7b cd 13  |.{....A......{..|
00000110  8d 64 10 66 61 c3 e8 1e  00 4f 70 65 72 61 74 69  |.d.fa....Operati|
00000120  6e 67 20 73 79 73 74 65  6d 20 6c 6f 61 64 20 65  |ng system load e|
00000130  72 72 6f 72 2e 0d 0a 5e  ac b4 0e 8a 3e 62 04 b3  |rror...^....>b..|
00000140  07 cd 10 3c 0a 75 f1 cd  18 f4 eb fd 00 00 00 00  |...<.u..........|
00000150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
This is the boot sector. One of the fun things about ISO9660 is that it doesn't have a boot sector in the usual x86 sense - firmwares are expected to read enough of the filesystem that they can find the bootloader in it and run it directly. x86 isn't really smart enough to manage that, so it uses something called El Torito[2]. In any case, this is usually empty space on an x86 CD. But with an increasing number of systems shipping without optical drives, real CD installs are decreasing in popularity. We use a piece of software called isohybrid that allows the building of ISO9660 images that can be written directly onto a USB stick. Asking a machine to boot off them will execute the boot sector located here, which then loads a real bootloader that's capable of reading ISO and booting the OS. It'll just be ignored when it's on a real CD.

There's one difference here, though. The isohybrid bootsector has been modified so that the first 32 bytes are just noops, and this has been inserted:
00000000  45 52 08 00 00 00 90 90  00 00 00 00 00 00 00 00  |ER..............|
45 52 ("ER") indicates the presence of an Apple partition map. This will become important later. 0800 indicates that it's using 2048-byte sectors. The 9090 is a lie to convince the firmware that it's not a zero-sized disk without representing dangerous code. We need an Apple partition map because some older Macs won't boot off CD unless the CD has one. But it's sitting right at the start of the boot sector, and this code is going to be executed. Thankfully, the entire Apple header decodes to
00000000  45                inc bp
00000001  52                push dx
00000002  0800              or [bx+si],al
00000004  0000              add [bx+si],al
00000006  90                nop
00000007  90                nop
00000008  0000              add [bx+si],al
0000000A  0000              add [bx+si],al
0000000C  0000              add [bx+si],al
0000000E  0000              add [bx+si],al
00000010  0000              add [bx+si],al
00000012  0000              add [bx+si],al
00000014  0000              add [bx+si],al
00000016  0000              add [bx+si],al
00000018  0000              add [bx+si],al
0000001A  0000              add [bx+si],al
0000001C  0000              add [bx+si],al
0000001E  0000              add [bx+si],al
which is completely harmless - we can execute all these instructions without any interesting changes in state. They'll all be undone by the rest of the boot sector.
000001b0  14 05 00 00 00 00 00 00  4c 1e ed 76 00 00 80 00  |........L..v....|
000001c0  01 00 00 3f a0 89 00 00  00 00 00 50 14 00 00 fe  |...?.......P....|
000001d0  ff ff ef fe ff ff a4 00  00 00 70 04 00 00 00 fe  |..........p.....|
000001e0  ff ff 00 fe ff ff 44 05  00 00 c0 08 00 00 00 00  |......D.........|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
This is the MBR partition table. The aim here was to produce media that would boot via BIOS just as well as it does via EFI, and it turns out that there are some systems that refuse to BIOS-boot off GPT media. So we need an MBR partition map. The first entry covers the entire disk and is of type 0. This is important, because some EFI implementations are strict about MBR parsing - if there's an MBR with overlapping partitions, the entire MBR will be ignored. Inconvenient. Fortunately, we've got the source code to this code, and it turns out that partitions of type 0 are ignored when performing this check. So, there's a partition of type 0.

Why does it cover the entire disk? Once we've booted the OS, we need to be able to read the ISO image contained on the USB stick. That means the kernel needs to be able to mount it, which means we need a partition entry that covers the entire disk. Linux is perfectly happy mounting a filesystem from a partition of type 0.

So, the next partition. This is an EFI boot partition that points at the embedded VFAT El-Torito image. Some firmware will decide that we've got an MBR and so will only boot off a partition that exists in it. So, here's an MBR partition to keep them happy.

The final partition covers the embedded HFS+ image. It's there purely for convenience - it means we can access it under Linux in order to update its contents for testing purposes.
00000200  45 46 49 20 50 41 52 54  00 00 01 00 5c 00 00 00  |EFI PART....\...|
00000210  09 27 93 7e 00 00 00 00  01 00 00 00 00 00 00 00  |.'.~............|
00000220  fe 4f 14 00 00 00 00 00  30 00 00 00 00 00 00 00  |.O......0.......|
00000230  de 4f 14 00 00 00 00 00  2a 26 0f 37 23 c9 7f 4f  |.O......*&.7#..O|
00000240  90 df 5e fe 0a 60 1c b0  10 00 00 00 00 00 00 00  |..^..`..........|
00000250  80 00 00 00 80 00 00 00  ec 70 63 c1 00 00 00 00  |.........pc.....|
00000260  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
And here we have the GPT header. Nothing complicated here, other than it indicates that the first partition descriptor is at LBA 0x10, ie byte 0x2000 - that's further into the disk than normal. That leaves us enough space to fit the Apple partition entries.

Why have a GPT at all? The EFI spec says that machines should boot fine from an MBR partition. Sadly, not all seem to. It also lets us represent the HFS+ partition in a way that makes the Mac firmware happy.
00000800  50 4d 00 00 00 00 00 03  00 00 00 01 00 00 00 10  |PM..............|
00000810  41 70 70 6c 65 00 00 00  00 00 00 00 00 00 00 00  |Apple...........|
00000820  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000830  41 70 70 6c 65 5f 70 61  72 74 69 74 69 6f 6e 5f  |Apple_partition_|
00000840  6d 61 70 00 00 00 00 00  00 00 00 00 00 00 00 00  |map.............|
00000850  00 00 00 00 00 00 00 0a  00 00 00 03 00 00 00 00  |................|
00000860  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
2K into the disk, here's an Apple partition map. It's 2K into the disk because we set the sector size to 2K in the partition map header. Why did we do that? Because the default is 512 bytes, and if we'd put the partition map at 512 bytes it would have been on top of the GPT header. Why 2K rather than 1K? A couple of reasons. First, the Apple partition map is only used when we boot off an actual CD, and the CD sector size is genuinely 2K. Secondly, because CDs have a sector size of 2K, 2K is a value that's actually been tested in the real world. It's nice to avoid tempting fate.
00001000  50 4d 00 00 00 00 00 03  00 00 00 29 00 00 04 70  |PM.........)...p|
00001010  45 46 49 00 00 00 00 00  00 00 00 00 00 00 00 00  |EFI.............|
00001020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001030  41 70 70 6c 65 5f 48 46  53 00 00 00 00 00 00 00  |Apple_HFS.......|
00001040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001050  00 00 00 00 00 00 04 70  00 00 00 33 00 00 00 00  |.......p...3....|
00001060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001800  50 4d 00 00 00 00 00 03  00 00 01 51 00 00 08 c0  |PM.........Q....|
00001810  45 46 49 00 00 00 00 00  00 00 00 00 00 00 00 00  |EFI.............|
00001820  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001830  41 70 70 6c 65 5f 48 46  53 00 00 00 00 00 00 00  |Apple_HFS.......|
00001840  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001850  00 00 00 00 00 00 08 c0  00 00 00 33 00 00 00 00  |...........3....|
00001860  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
The Apple partition map entries. One partition covers the entire disk, the other the embedded HFS+ filesystem. Why do this? Because not all Macs understand EFI El Torito, so won't EFI boot a CD unless there's an Apple partition map. Why have an HFS+ partition at all? Because the same Macs won't boot off FAT.
00002000  a2 a0 d0 eb e5 b9 33 44  87 c0 68 b6 b7 26 99 c7  |......3D..h..&..|
00002010  d0 84 a5 d4 aa 89 e0 40  81 f9 fc e4 04 e9 c2 99  |.......@........|
00002020  00 00 00 00 00 00 00 00  10 4b 14 00 00 00 00 00  |.........K......|
00002030  00 00 00 00 00 00 00 00  49 53 4f 48 79 62 72 69  |........ISOHybri|
00002040  64 20 49 53 4f 00 49 53  4f 48 79 62 72 69 64 00  |d ISO.ISOHybrid.|
00002050  41 70 70 6c 00 00 00 00  00 00 00 00 00 00 00 00  |Appl............|
00002060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002080  a2 a0 d0 eb e5 b9 33 44  87 c0 68 b6 b7 26 99 c7  |......3D..h..&..|
00002090  68 d5 e0 27 72 83 c6 4c  a7 ae 92 dd ed 6c 89 71  |h..'r..L.....l.q|
000020a0  a4 00 00 00 00 00 00 00  13 05 00 00 00 00 00 00  |................|
000020b0  00 00 00 00 00 00 00 00  49 53 4f 48 79 62 72 69  |........ISOHybri|
000020c0  64 00 41 70 70 6c 65 00  41 70 70 6c 00 00 00 00  |d.Apple.Appl....|
000020d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002100  00 53 46 48 00 00 aa 11  aa 11 00 30 65 43 ec ac  |.SFH.......0eC..|
00002110  68 d5 e0 27 72 83 c6 4c  a7 ae 92 dd ed 6c 89 71  |h..'r..L.....l.q|
00002120  44 05 00 00 00 00 00 00  03 0e 00 00 00 00 00 00  |D...............|
00002130  00 00 00 00 00 00 00 00  49 53 4f 48 79 62 72 69  |........ISOHybri|
00002140  64 00 41 70 70 6c 65 00  41 70 70 6c 00 00 00 00  |d.Apple.Appl....|
00002150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
Three GPT entries - one covers the entire CD, one covers the embedded FAT filesystem, one covers the embedded EFI filesystem. That ensures that they're all accessible to the firmware.
00008000  01 43 44 30 30 31 01 00  4c 49 4e 55 58 20 20 20  |.CD001..LINUX   |
00008010  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00008020  20 20 20 20 20 20 20 20  46 65 64 6f 72 61 2d 4c  |        Fedora-L|
00008030  69 76 65 43 44 20 20 20  20 20 20 20 20 20 20 20  |iveCD           |
00008040  20 20 20 20 20 20 20 20  00 00 00 00 00 00 00 00  |        ........|
00008050  c4 12 05 00 00 05 12 c4  00 00 00 00 00 00 00 00  |................|
00008060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00008070  00 00 00 00 00 00 00 00  01 00 00 01 01 00 00 01  |................|
00008080  00 08 08 00 40 00 00 00  00 00 00 40 15 00 00 00  |....@......@....|
00008090  00 00 00 00 00 00 00 17  00 00 00 00 22 00 1d 00  |............"...|
000080a0  00 00 00 00 00 1d 00 08  00 00 00 00 08 00 70 05  |..............p.|
000080b0  01 09 30 36 f0 02 00 00  01 00 00 01 01 00 20 20  |..06..........  |
000080c0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
The ISO9660 superblock. This is completely standard. From here on there's nothing terribly surprising - the CD filesystem itself is entirely normal. The only slight oddity is that we have three embedded El Torito images. The first of these is a BIOS-bootable disk image. That'll be executed whenever the CD is put in a non-EFI machine. The second is a VFAT EFI boot image. That's used for the majority of EFI systems. The third is an HFS+ EFI boot image. There's no strict requirement for the HFS+ one to be an El Torito image - CD booting on Macs is already handled by the Apple partition map. Storing it as an El Torito is purely for convenience, since it guarantees correct alignment and avoids us having to parse the entire ISO9660 image to find its location when generating the partition maps.

In summary: Three partition maps, three bootable images, support for BIOS, UEFI and Mac platforms, works whether it's burned to a CD or written directly to a USB stick. I'm pretty pleased with that.

[1] Other than an awkward bug where something goes horribly wrong during Radeon graphics init, so Radeon-based Macs aren't working too well at the moment. We're working on it.

[2] The world decided that writing a real ISO9660 driver for BIOS was hard, so came up with El Torito. El Torito is a spec for embedding disk images inside ISO9660. There's a pointer to the disk image in the Cd header, so the BIOS simply reads a few blocks off CD, finds that pointer and then sets up a bunch of disk i/o interrupts to point at the embedded filesystem rather than a real disk. From that point on, the El Torito image simply behaves like a floppy or hard drive. This was a reasonable compromise given how resource limited older BIOS implementations were.

For reasons that aren't entirely clear, UEFI doesn't mandate that implementations support ISO9660. So even though our firmware is now sufficiently capable that the only thing standing between it and emacs is someone being sufficiently bored, we still use El Torito. Fortunately the spec allows multiple El Torito images to be embedded, so we can include one that's bootable by BIOS systems and another that's bootable by UEFI systems.

comment count unavailable comments

Feeds