GNOME.ORG

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

November 20, 2014

Galaxy Zoo for Android

I just released my Galaxy Zoo android app to the Google Play store. The Zooniverse team have adopted it as their official Galazy Zoo app for Android.

Like the Galaxy Zoo website, it asks you questions about a picture of a galaxy, with each question depending on the previous question. This “Citizen Science” helps astronomers to analyze the huge amount of images of galaxies provided, for instance, by the Hubble Space Telescope. There are several other Zooniverse projects, though most require more thought and have more complicated user interaction.

screenshot_nexus4_api21_classify_first screenshot_nexus4_api21_list

I have already released several beta versions to a handful of helpful testers, but now I’m nervous about it being publicly available. I’d rather not be bombarded with one-star reviews if there’s a bug I haven’t caught yet or if people don’t like something about the questions themselves.

There was a previous Galaxy Zoo android app that I think was in use until around 2012, but it stopped working with the latest version of the server and apparently wasn’t updated. It’s no longer available from the Google Play store. This new Galaxy Zoo android app is open source on github, so it should have more future. For instance, that would let other developers investigate problems if there are server changes, even if I don’t (though I would). Patches and pull requests are very welcome. There are even a few minor issues that I’d already like help with.

I’ve been working on this for the past few weeks, using it as a real-world exercise to learn about Android development, trying to do everything properly. I’ve enjoyed diving into something new, and it feels good to have gained the experience. However, Android development ultimately feels just as awkward as every other development environment I’ve ever worked with – no more nor less. I’ll write some follow-up blog entries about the technical parts of the adventure.

 

 

 

November 19, 2014

"Learn IT, Girl!" mentorship program just started!

This week is official beginning of "Learn IT, Girl!" program [1]. It's international program for woman, started by a few girls from Poland and Romania, invented at the Google Anita Borg Scholarship [2] retreat in 2014. A main aim is to learn by women particular programming language. Every scholar is guided by her own mentor, who helps her. Girls learn language by doing selected earlier project (which must be open-source project ofc).

I take a part in this program as a mentor, and my my mentee is Corina Teodorescu. She's from Romania and studies Marketing. Corina has decided to learn C#, and she's going to write an mobile app for phones with Android OS. Because of a lot really great ideas, she doesn't finally choose her project. She's choosing between RSS reader and application for downloading/uploading/hash-tagging images - she didn't make a decision, but I think, both are quite useful, and Corina can learn a lot by making one of them(what's the most important during this program :)

Program takes 3 months, and I believe, that would be great time for Corina and for me as well. I hope, Corina will learn a lot, and I'm going to improve my teaching skills too. We will have fun for sure :)

 Wish me and Corina luck!

Learn IT, Girl!


Links
[1] https://sites.google.com/site/learnitgirl/
[2] http://www.google.com/anitaborg/

Switching between nouveau and the nVIDIA proprietary OpenGL driver in (Debian) GNU/Linux

So lately I’ve been devoting my time in Igalia around the GNU/Linux graphics stack focusing, more specifically, in Mesa, the most popular open-source implementation of the OpenGL specification.

When working in Mesa and piglit, its testing suite, quite often you would like to compare the results obtained when running a specific OpenGL code with one driver or another.

In the case of nVIDIA graphic cards we have the chance of comparing the default open source driver provided by Mesa, nouveau, or the proprietary driver provided by nVIDIA. For installing the nVIDIA driver you will have to run something like:

root$ apt-get install linux-headers nvidia-driver nvidia-kernel-dkms nvidia-xconfig

Changing from one driver to another involves several steps so I decided to create a dirty script for helping with this.

The actions done by this script are:

  1. Instruct your X Server to use the adequate X driver.

    These instructions apply to the X.org server only.

    When using the default nouveau driver in Debian, the X.org server is able to configure itself automatically. However, when using the nVIDIA driver you most probably will have to instruct the proper settings to X.org.

    nVIDIA provides the package nvidia-xconfig. This package provides a tool of the same name that will generate a X.org configuration file suitable to work with the nVIDIA X driver:

    root$ nvidia-xconfig 
    
    WARNING: Unable to locate/open X configuration file.
    
    Package xorg-server was not found in the pkg-config search path.
    Perhaps you should add the directory containing `xorg-server.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'xorg-server' found
    New X configuration file written to '/etc/X11/xorg.conf'

    I have embedded this generated file into the provided custom script since it is suitable for my system:

    echo 'Section "ServerLayout"
        Identifier     "Layout0"
        Screen      0  "Screen0"
        InputDevice    "Keyboard0" "CoreKeyboard"
        InputDevice    "Mouse0" "CorePointer"
    EndSection
    
    Section "Files"
    EndSection
    
    Section "InputDevice"
        # generated from default
        Identifier     "Mouse0"
        Driver         "mouse"
        Option         "Protocol" "auto"
        Option         "Device" "/dev/psaux"
        Option         "Emulate3Buttons" "no"
        Option         "ZAxisMapping" "4 5"
    EndSection
    
    Section "InputDevice"
        # generated from default
        Identifier     "Keyboard0"
        Driver         "kbd"
    EndSection
    
    Section "Monitor"
        Identifier     "Monitor0"
        VendorName     "Unknown"
        ModelName      "Unknown"
        HorizSync       28.0 - 33.0
        VertRefresh     43.0 - 72.0
        Option         "DPMS"
    EndSection
    
    Section "Device"
        Identifier     "Device0"
        Driver         "nvidia"
        VendorName     "NVIDIA Corporation"
    EndSection
    
    Section "Screen"
        Identifier     "Screen0"
        Device         "Device0"
        Monitor        "Monitor0"
        DefaultDepth    24
        SubSection     "Display"
            Depth       24
        EndSubSection
    EndSection
    ' > /etc/X11/xorg.conf

    I would recommend you to substitute this with another configuration file generated with nvidia-xconfig on your system.

  2. Select the proper GLX library.

    Fortunately, Debian provides the alternatives mechanism to select between one or the other.

    ALTERNATIVE=""

    ALTERNATIVE="/usr/lib/mesa-diverted"

    ALTERNATIVE="/usr/lib/nvidia"

    update-alternatives --set glx "${ALTERNATIVE}"

  3. Black list the module we don’t want the Linux kernel to load on start up.

    Again, in Debian, the nVIDIA driver package installs the file /etc/nvidia/nvidia-blacklists-nouveau.conf that is linked, then, from /etc/modprobe.d/nvidia-blacklists-nouveau.conf instructing that the open source nouveau kernel driver for the graphic card should be avoided.

    When selecting nouveau, this script removes the soft link creating a new file which, instead of black listing nouveau’s driver, does it for the nVIDIA proprietary one:

    rm -f /etc/modprobe.d/nvidia-blacklists-nouveau.conf
        echo "blacklist nvidia" > /etc/modprobe.d/nouveau-blacklists-nvidia.conf

    When selecting nVIDIA, the previous file is removed and the soft link is restored.

  4. Re-generate the image used in the inital booting.

    This will ensure that we are using the proper kernel driver from the beginning of the booting of the system:

    update-initramfs -u

With these actions you will be already able to switch your running graphic driver.

You will switch to nouveau with:

root$ <path_to>/alternate-nouveau-nvidia.sh nouveau
update-alternatives: using /usr/lib/mesa-diverted to provide /usr/lib/glx (glx) in manual mode
update-initramfs: Generating /boot/initrd.img-3.17.0

nouveau successfully set. Reboot your system to apply the changes ...

And to the nVIDIA proprietary driver with:

root$ <path_to>/alternate-nouveau-nvidia.sh nvidia
update-alternatives: using /usr/lib/nvidia to provide /usr/lib/glx (glx) in manual mode
update-initramfs: Generating /boot/initrd.img-3.17.0

nvidia successfully set. Reboot your system to apply the changes ...

It is recommended to reboot the system although theoretically you could unload the kernel driver and restart the X.org server. The reason is that it has been reported that unloading the nVIDIA kernel driver and loading a different one is not always working correctly.

I hope this will be helpful for your hacking time!

November 18, 2014

GSoC Reunion Recap

The GSoC Reunion was a really great experience for me. I travelled from Edinburgh for the event. It was wonderful chatting with so many different FLOSS enthusiasts all in one place and I made lots of new buddies who I’ll definitely keep in touch with.


On the first day, Google rented out a theme park for a few hours, letting us go wild. We successfully fought the urge to be sick on the rides as they spun us around. Afterwards, we were invited to the San Jose Tech Museum where we got to listen to Linus Torvalds speak about the qualities of good code. The museum’s exhibitions were very interactive and I especially liked the one which demonstrated how ice hockey protective equipment is designed for goalies. I hadn't realised how sophisticated it is!


An "unconference" was held across Saturday and Sunday, and I really enjoyed the sessions I attended. For those who have never been to an unconference, it’s much more interactive than a typical conference talk. People ask questions and make comments throughout, making it a discussion. It’s definitely a format I can get on with!


One conversation which had begun around ending misogynistic trolling on internet dating sites got really interesting because it quickly developed into two groups who were each keen to address sexism from different angles. One group focused on online sexism and the other on sexism at conferences and other events. The latter group went on to discuss establishing a universal code of conduct available for FLOSS projects to adopt if they choose, while the former group considered developing software to deal with abuse on IRC. Everyone got so engaged that we chatted until the notetaker's wrists were sore from 2 or 3 hours of typing. It was incredibly heartening to see so many men who are interested discussing these issues in one place. I have never seen anything like that before in my life! It takes quite a lot of objectivity and emotional intelligence to be able to stand up for the rights of a group you aren’t part of.


Another session was led by a Googler and we discussed the potential pitfalls of publishing work in the public domain. Laws vary widely around the world, and there are places where the work may unintentionally remain under copyright protection. That is a compelling reason to use free or open source licenses. There have been few landmark court cases since FLOSS licensing came along, so it’s difficult to be certain what things will mean in practical terms. That session made me quite interested in learning more about copyright law.


On Sunday, there was a talk on The GNOME Foundation’s Outreach Program for Women (OPW) which was well attended. I learned that projects have to demonstrate their commitment by finding funding for a student before they can take part. I think that is a good idea, but it is a shame that there are not more sponsors available so smaller projects can get involved. Hopefully as OPW continues successfully helping women get started in open source development, more companies will step forward as sponsors.


I am always keen to talk about accessible software, so I initiated an unconference discussion on the topic in one of the rooms. Although that session was not well attended, those who were there had a lot to say and were very engaged with the idea of establishing a common interest group for accessibility developers. Get in touch if that sounds interesting to you too.

Finally, we got to visit the Google Headquarters on the final day of the reunion. We didn’t get to tour inside the offices, but I at least got a peek at the famous indoor slide… Maybe next time I’ll get a chance to go up to the top.

This post can also be found on Google's Open Source Blog.

November 17, 2014

Bahn Bonus Points Saemmeln

mdb_166803_saemmel_bc_4zu1_734x183_hq

The Bahn currently has a Web-based game for you to win some of their loyalty points. It’s not a very exciting game, but you get up to 500 points which is half a free ride across the country. (You get the other half when signing up for their program.)

In order to get these 500 points you need to play for an hour or so. Or you observe the Web traffic your browser generates and look closely. You’ll see that the Flash applet fetches a token from the server and sends your result, along with the token and some hash, to the server. How to get the correct hash you ask? Worry not, you will get the correct hash from the server if you don’t send the correct one. You can resend your request with the hash the server sent you and your POST will be accepted. Neat.

I don’t know why they send the “correct_hash”, but it’s obviously a bad idea.

PS: It seems that Kazam has troubles recording my mouse pointer position correctly.

networks without networks

doug engelbart:

I need to quickly sketch out what I see as the goal - the way to get the significant payoff from using computers to augment what people can do. This vision of success has not changed much for me over fifty years - it has gotten more precise and detailed - but it is pointed at the same potential that I saw in the early 1950s. It is based on a very simple idea, which is that when problems are really difficult and complex - problems like addressing hunger, containing terrorism, or helping an economy grow more quickly - the solutions come from the insights and capabilities of people working together. So, it is not the computer, working alone, that produces a solution. But is the combination of people, augmented by computers. Doug Engelbart

once again, doug engelbart hits the nail on the head. yes, we humans are a very collaborative bunch. not for nothing we were able to hunt mammoths, build cities and fly to the moon. and still after half a century, this idea of augmenting human intellect with computers gets little attention. i recently found this magnificent piece by paul ford, subtitled networks without networks:

Technology is what we share. I don't mean "we share the experience of technology.” I mean: By my lights, people very often share technologies with each other when they talk. Strategies. Ideas for living our lives. We do it all the time. Parenting email lists share strategies about breastfeeding and bedtime. Quotes from the Dalai Lama. We talk neckties, etiquette, and Minecraft, and tell stories that give us guidance as to how to live. A tremendous part of daily life regards the exchange of technologies. We are good at it. It's so simple as to be invisible. Can I borrow your scissors? Do you want tickets? I know guacamole is extra. The world of technology isn't separate from regular life. It's made to seem that way because of, well... capitalism. Tribal dynamics. Territoriality. Because there is a need to sell technology, to package it, to recoup the terrible investment. So it becomes this thing that is separate from culture. A product. Paul Ford

the world of technology isn't separate from regular life. it isn't. but all too often technology is reduced to the man and the machine. i hope this line of thought changes. soon.

Builder Update

I've been really busy the last few weeks, so I've been short on updates.

In particular, I've been trying to get everything solidified for the fundraising campaign. That's a lot more work than I ever imaged. Definitely harder for me than writing software.

But there has been some development since the last update, including updates to the wiki.

  • Started on a new GtkSourceStyleScheme for Builder. It's based on colors from the Mozilla developer site. I think I'd like to use FiraMono as the default font too. If you want to work on this, let me know. There are plenty of people better at this than me.
  • I've been working on lots of new designs for how workspaces will work. I'll try to get the design sketches up soon.
  • You can see the search box now, to get an idea of how it will look, but nothing is wired up yet. The Global Search feature will be central to Builder.
  • Python and XML auto indenters have been added to compliment the C89 auto indenter.
  • Some basic support for gnome-code-assistance has been added so you'll see errors and warnings as you type. I have some bugs still to work out here that are my fault. I miss-understood how some things worked and need to find time to fix them.
  • Various improvements to C89 auto indenter.
  • Various improvements to VIM mode.
  • Style Scheme and Font can be configured in Preferences.
  • You can configure editor options per-language in Preferences.
  • We try to install reasonable defaults for some major languages upon first run. Feel free to suggest some more or better yet submit a patch. The file in question is src/resources/language/defaults.ini
  • CommandBar has been modified to look more like Firefox.

As soon as the fundraiser is launched, I'm really looking forward to get back to working on the core workspace design and editor features. Also, I think the Global Search is going to be a lot of fun to implement.

Cheers!

November 16, 2014

2014-11-16: Sunday

  • Off to the venue, more meetings, hacking on misc OpenGL-ness with Markus; plugged away at various irritating bugs, helped to explain the recent exciting revival in the LibreOffice UX team - worth giving it another try. Out for a swift beer, and on to the airport with Markus. Flights, missed bus; waited at Heathrow until 5am for a coach.

November 15, 2014

2014-11-15: Saturday

  • Sleep; to the venue, some hackery, met with various interesting people in the French LibreOffice scene, great to see another Michael hacking away at easy-hacks, and lots of interest. Beer & nibbles event in the evening, out rather late at a sandwich on a block type place.

with a little help

this is a request for help.

GTK+ 3.16 will have OpenGL support out of the box.

at least, it will have it on X11 and Wayland.

if you are using (or you plan to use) GTK+ 3.x on Windows or MacOS X, and you know how to use OpenGL on those two platforms, please consider helping out the GTK+ developers by implementing the GdkGLContext API using WGL and AppleGL.

we’d really like to get all backends working out of the box when we release GTK+ 3.16.0, next year.

testing and feedback is also very much appreciated.

in the meantime, I’m doing some much needed spring cleaning in the GtkGLExt and GtkGLArea products on Bugzilla.


Update: thanks to Brion Vibber, there’s already a preliminary patch for implementing GdkGLContext on MacOS X. now it’s up to the Windows developers to step up their game. :-)

Update: Fan Chun-wei is looking into Windows support, so we should have a patchset for it soon!

November 14, 2014

Ipsilon and FedOAuth merge complete, FedOAuth deprecation

Ipsilon and FedOAuth merge complete, FedOAuth deprecation

As you might know, I currently maintain an open source identity provider project named FedOAuth.

Since September, I have been working with Simo Sorce to merge FedOAuth with another identity provider called Ipsilon.

As of today, I deem this merge complete: Ipsilon has all major FedOAuth features now. As such, I am hereby announcing that FedOAuth will be in maintenance-only mode as of today, meaning only important bugfixes/security changes will be made.

My advice to any current installations of FedOAuth is to migrate to Ipsilon soon. If you need any help with this, please feel free to get in touch with me.

Also, FedOAuth will reach the End-Of-Life at February 1st, 2015: as of that date, no new releases will be made for FedOAuth, so please make sure to migrate or get in contact with me before that date.

What now?

I will continue to contribute to Ipsilon, and make sure it becomes better over time! More blog posts on Ipsilon and its advantages are coming soon, so be sure to look forward to those!

If you want to congratulate me and Simo with getting the merge done, or have any other feedback on Ipsilon, feel free to pop by on #ipsilon at FreeNode.

If you want to contact me, you can either ping me on FreeNode (puiterwijk), or drop an email to puiterwijk@redhat.com.

on yakshave, on color, on cosines, on glitchen

Hold on to your butts, kids, because this is epic.

on yaks

As in all great epics, our prideful, stubborn hero starts in a perfectly acceptable state of things, decides on a lark to make a small excursion, and comes back much much later to inflict upon you pictures from his journey.

So. I have a web photo gallery but I don't take many pictures these days. Dealing with photos is a bit of a drag, and the ways that are easier like Instagram or what-not give me the (peer, corporate, government: choose 3) surveillance hives. So, I had vague thoughts that I should update my web gallery. Yakpoint 1.

At the same time, my web gallery was written for mod_python on the server, and I don't like hacking in Python any more and kinda wanted to switch away from Apache. Yakpoint 2.

So I rewrote the server-side part in Scheme. (Yakpoint 3.) It worked fine but I found I needed the ability to get the dimensions of files on the server, so I wrote a quick-and-dirty JPEG parser. Yakpoint 4.

I needed EXIF data as well, as the original version displayed EXIF data, and for that I used a binding to libexif that I had written a few years ago when I thought about starting this project (Yakpoint -1). However I found some crashers in the library, because it had never really been tested in production, and instead of fixing them I said "what the hell, I'll just write an EXIF parser". (Yakpoint 5.) So I did and adapted the web gallery to use it (Yakpoint 6, for the adaptation.)

At this point, I looked back, and looked forward, and looked all around, and all was good, but what was with this uneasiness I was feeling? And indeed, I hadn't actually made anything better, and I wasn't taking more photos, and the workflow was the same.

I was also concerned about the client side of things, which was still in Python and using some breakage-prone legacy libraries to do the photo scaling and transformations and what-not, and relied on a desktop application (f-spot) of dubious future. So I started to look at what it would take to port that script to Scheme (Yakpoint 7). Well it used some legacy libraries to copy files over SSH (gnome-vfs; switching away from that would be Yakpoint 8) and I didn't want to make a Scheme GIO binding (Yakpoint 9, narrowly avoided), and I then -- and then, dear reader -- so then I said "well WTF my caching story on the server is crap anyway, I never know when the sqlite database has changed or not so I never know what responses I can cache, what I really want is a functional datastore" (Yakpoint 10), which is what I have with Git and Tekuti (Yakpoint of yore), and so why not just store my photos in Git like I do in Tekuti for blog posts and serve them from there, indexing as needed? Of course I'd need some other server software (Yakpoint of fore, by which I meantersay the future), but then I could just git push to update my photo gallery, and I wouldn't have to endure the horror that is GVFS shelling out to ssh in a FUSE daemon (Yakpoint of ne'er).

So. After mulling over these thoughts for a while I decided, during an autumnal walk on the Salève in which we had the greatest views of Mont Blanc everrrrr and yet where are the photos?, that really what I needed was new photo management software, not just a web gallery. I should be able to share photos from my phone or from my desktop, fix them up either place, tag and such, and OK woo hoo! Such is the future! And the present for many people? Thing is, I also needed good permissions management (Yakpoint what, 10 I guess?), because you know a dude just out of college is not the same as that dude many years later. Which means serving things over HTTPS (Yakpoints 11-47) in such a way that the app has some good control over who gets what.

Well. Anyway. My mind ran ahead, and runs ahead, and yet we haven't actually tasted the awesome sauce yet. So! The photo management software, whereever it lives, needs to rotate photos at least, and scale them down to a few resolutions. I smell a yak! I looked at jpegtran which can do some lossless rotations but it's not available as a library, which is odd; and really I don't like shelling out for core program functionality, because every time I deal with the file system it's the wild west of concurrent mutation. If naming things is one of the two hardest problems in computer science, the file system is the worst because you have to give a global name to every intermediate value.

At the same time to scale images, what was I to do? Make a binding to libjpeg? Well I started (Yakpoint 48) but for reals kids, libjpeg is not fun. It works great and is really clever but

  1. it's approximately impossible to use from a dynamic ffi; you want a compiler to verify that you are using the right structure definitions

  2. there has been an inane ABI and format break imposed by the official IJG libjpeg but which other implementations have not followed, but how could you know which one you are using?

  3. the error handling facility encourages longjmp in C programs; somewhat terrifying

  4. off-heap image manipulation libraries always interact poorly with GC, because the GC only sees the small pointer to the off-heap image, and so doesn't GC often enough

  5. I have zero guarantee that libjpeg won't change ABI in weird ways, and I don't want to touch this software for the next 10 years

  6. I want to do jpegtran-like lossless transformations, but that's not available as a library, and it's totes ridics that binding libjpeg does not help you out here

  7. it's still an unsafe C library, battle-tested yes, but terrifyingly unsafe, and I'd be putting it on my server and who knows?

Friends, I arrived at the pasture, and I, I chose the yak less shaven. I took my lame JPEG parser and turned it into a full decoder (Yakpoint 49), realized it wasn't much more work to do an encoder (Yakpoint 50), and implemented the lossless transformations (Yakpoint 51).

on haters

Before we go on, I know some people would think "what is this kid about". I mean, custom gallery software, a custom JPEG library of all things, all bespoke, why don't you just use off-the-shelf solutions? Why aren't you normal and use a normal language and what about the best practices and where's your business case and I can't go on about this because there's a technical term for people that say this kind of thing and it's "hater".

Thing is, when did a hater ever make anything cool? Come to think of it, when did a hater make anything at all? In my experience the most vocal haters have nothing behind their names except a long series of pseudonymous rants in other people's comment boxes. So friends, in the joyful spirit of earning-anew, let's talk about JPEG!

on color

JPEG is a funny thing. Photos are our lives and our memories, our first steps and our friends, and yet I for one didn't know very much about them. My mental model that "a JPEG is a rectangle of pixels" doesn't turn out to be quite right.

If you actually look in a normal JPEG, you see three planes of information. If I take this image, for example:

If I decode it, actually I get three images. Here's the first one:

This is just the greyscale version of the image. So, storytime! Remember black and white television? We had an old one that got moved around the house sometimes, like if Mom was working at something in the kitchen. We also had a color one in the living room, and you could watch one or the other and they showed the same stuff. Strange when you think about it though -- one being in color and the other not. Well it turns out that color was literally just added on, both historically and technically. The main broadcast was still in black and white, and then in one part of the frequency band there were separate color signals, which color TVs would pick up, mix with the black and white signal, and come out with color. Wikipedia notes that "color TV" was really just "colored TV", which is a phrase whose cleverness I respect. Big ups to the W P.

In the context of JPEG, this black-and-white signal is sometimes called "luma", but is more precisely called Y', where the "prime" (the apostrophe) indicates that the signal has gamma correction applied.

In the image above, I replaced the color planes (sometimes collectively called the "chroma") with zeroes, while losslessly keeping the luma. Below is the first color plane, with the Y' plane replaced with a uniform 50% luma, and the other color plane replaced with zeros.

This color signal is technically known as CB, which may be very imperfectly understood as the bluish component of the color. Well the original image wasn't very blue, so we don't see very much here.

Indeed, our eyes have a harder time seeing differences in color than differences in intensity. Apparently this goes all the way down to biology -- we have more receptors in our eyes for "black and white" and fewer for color.

Early broadcasters took advantage of this difference in perception by actually devoting more bandwidth in their broadcasts to luma than to chroma; if you check the Wikipedia page you will see that the area in the spectrum allocation devoted to color is much smaller than the area devoted to intensity. So it is in JPEG: the above image being half-width indicates that actually we're just encoding one CB sample for every two Y' samples.

Finally, here we have the CR color plane, which can loosely be thought of as the "redness" of the image.

These test images and crops preserve the actual encoding of this photo as it came from my camera, without re-encoding. That's partly why there's not much interesting going on; with the megapixels these days, it's hard to fit much of anything in a few hundred pixels square. This particular camera is sub-sampling in the horizontal direction, but it's also common to subsample vertically as well, producing color planes that are half-width and half-height. In my limited investigations I have found that cameras tend to sub-sample just in the X direction, producing what they call 4:2:2 images, and that standard software encoders subsample in both, producing 4:2:0.

Incidentally, properly scaling up the color planes is quite an irritating endeavor -- the standard indicates that the color is sampled between the locations of the Y' samples ("centered" chroma), but these images originally have EXIF data that indicates that the color samples are taken at the position of the first Y' sample ("co-sited" chroma). I'm pretty sure libjpeg doesn't delve into the EXIF to check this though, so it would seem that all renderings I have seen of these photos are subtly off.

But how do you get proper color out of these strange luma and chroma things? Well, the Y'CBCR colorspace is really just the same color cube as RGB, except rotated: the Y' axis traverses the diagonal from (0, 0, 0) (black) to (255, 255, 255) (white). CB and CR are perpendicular to that diagonal, pointing towards blue or red respectively. So to go back to RGB, you multiply by a matrix to rotate the cube.

It's not a very intuitive color system, as you can see from the images above. For one thing, at zero or full luma, the chroma axes have no meaning; black and white can have no hue. Indeed if you imagine trying to fit a cube corner-down into a similar-sized box, you end up either having empty space in the box, or you have to cut off corners from the cube, or both. Cut corners means that bits of the Y'CBCR signal are wasted; empty space means there are RGB colors that are not representable in Y'CBCR. I'm not sure, but I think both are true for the particular formulation of Y'CBCR used in JPEG.

There's more to say about color here but frankly I don't know enough to do so, even though I worked in digital video for many years. If this is something you are mildly interested in, I highly, highly recommend watching Wim Taymans' presentation at this year's GStreamer conference. He takes a look at color in video that is constructive, building up from biology through math to engineering. His is a principled approach rather than a list of rules. It really clarified a number of things for me (and opened doors to unknown unknowns beyond).

on cosines

Where were we? Right, JPEG. So the proper way to understand what JPEG is is to understand the encoding process. We've covered colorspace conversion from RGB to Y'CBCR and sub-sampling. Next, the image canvas is divided into equal-sized "macroblocks". (These are called "minimum coded units" (MCUs) in the JPEG context, but in video they are usually called macroblocks, and it's a better name.) Without sub-sampling, each macro-block will contain one 8-sample-by-8-sample block for each component (Y', CB, CR) of the image. In my images above, the canvas space corresponding to one chroma block is the space of two luma blocks, so the macroblocks will be 16 samples wide and 8 samples tall, and contain two Y' blocks and one each of CB and CR. If the image canvas can't be evenly divided into macroblocks, it is padded to fit, usually by duplicating the last column or row of samples.

Then to make a JPEG, each block is encoded separately, then the whole thing is just written out to a file, and you're done!

This description glosses over a couple of important points, but it's a good big-picture view to have in mind. The pipeline goes from RGB pixels, to a padded RGB canvas, to separate Y'CBCR planes, to a possibly subsampled set of those planes, to macroblocks, to encoded macroblocks, to the file. Decoding is the reverse. It's a totally doable, comprehensible thing, and that was one of the big takeaways for me from this project. I took photography classes in high school and it was really cool to see how to shoot, develop, and print film, and this is similar in many ways. The real "film" is raw-format data, which some cameras produce, but understanding JPEG is like understanding enlargers and prints and fixer baths and such things. It's smelly and dark but pretty cool stuff.

So, how do you encode a block? Well peoples, this is a kinda cool thing. Maybe you remember from some math class that, given n uniformly spaced samples, you can always represent that series as a sum of n cosine functions of equally spaced frequencies. In each litle 8-by-8 block, that's what we do: a "forward discrete cosine transformation" (FDCT), which is just multiplying together some matrices for every point in the block. The FDCT is completely separable in the X and Y directions, so the space of 8 horizontal coefficients multiplies by the space of 8 vertical coefficients at each column to yield 64 total coefficients, which is not coincidentally the number of samples in a block.

Funny thing about those coefficients: each one corresponds to a particular horizontal and vertical frequency. We can map these out as a space of functions; for example giving a non-zero coefficient to (0, 0) in the upper-left block of a 8-block-by-8-block grid, and so on, yielding a 64-by-64 pixel representation of the meanings of the individual coefficients. That's what I did in the test strip above. Here is the luma example, scaled up without smoothing:

The upper-left corner corresponds to a frequency of 0 in both X and Y. The lower-right is a frequency of 4 "hertz", oscillating from highest to lowest value in both directions four times over the 8-by-8 block. I'm actually not sure why there are some greyish pixels around the right and bottom borders; it's not a compression artifact, as I constructed these DCT arrays programmatically. Anyway. Point is, your lover's smile, your sunny days, your raw urban graffiti, your child's first steps, all of these are reified in your photos as a sum of cosine coefficients.

The odd thing is that what is reified into your pictures isn't actually all of the coefficients there are! Firstly, because the coefficients are rounded to integers. Mathematically, the FDCT is a lossless operation, but in the context of JPEG it is not because the resulting coefficients are rounded. And they're not just rounded to the nearest integer; they are probably quantized further, for example to the nearest multiple of 17 or even 50. (These numbers seem exaggerated, but keep in mind that the range of coefficients is about 8 times the range of the original samples.)

The choice of what quantization factors to use is a key part of JPEG, and it's subjective: low quantization results in near-indistinguishable images, but in middle compression levels you want to choose factors that trade off subjective perception with file size. A higher quantization factor leads to coefficients with fewer bits of information that can be encoded into less space, but results in a worse image in general.

JPEG proposes a standard quantization matrix, with one number for each frequency (coefficient). Here it is for luma:

(define *standard-luma-q-table*
  #(16 11 10 16 24 40 51 61
    12 12 14 19 26 58 60 55
    14 13 16 24 40 57 69 56
    14 17 22 29 51 87 80 62
    18 22 37 56 68 109 103 77
    24 35 55 64 81 104 113 92
    49 64 78 87 103 121 120 101
    72 92 95 98 112 100 103 99))

This matrix is used for "quality 50" when you encode an 8-bit-per-sample JPEG. You can see that lower frequencies (the upper-left part) are quantized less harshly, and vice versa for higher frequencies (the bottom right).

(define *standard-chroma-q-table*
  #(17 18 24 47 99 99 99 99
    18 21 26 66 99 99 99 99
    24 26 56 99 99 99 99 99
    47 66 99 99 99 99 99 99
    99 99 99 99 99 99 99 99
    99 99 99 99 99 99 99 99
    99 99 99 99 99 99 99 99
    99 99 99 99 99 99 99 99))

For chroma (CB and CR) we see that quantization is much more harsh in general. So not only will we sub-sample color, we will also throw away more high-frequency color variation. It's interesting to think about, but also makes sense in some way; again in photography class we did an exercise where we shaded our prints with colored pencils, and the results were remarkable. My poor, lazy coloring skills somehow rendered leaves lifelike in different hues of green; really though, they were shades of grey, colored in imprecisely. "Colored TV" indeed.

With this knowledge under our chapeaux, we can now say what the "JPEG quality" setting actually is: it's simply that pair of standard quantization matrices scaled up or down. Towards "quality 100", the matrix approaches all-ones, for no quantization, and thus minimal loss (though you still have some rounding, often subsampling as well, and RGB-to-Y'CBCR gamut loss). Towards "quality 0" they scale to a matrix full of large values, for harsh quantization.

This understanding also explains those wavey JPEG artifacts you get on low-quality images. Those artifacts look like waves because they are waves. They usually occur at sharp intensity transitions, which like a cymbal crash cause lots of high frequencies that then get harshly quantized. Incidentally I suspect (but don't know) that this is the same reason that cymbals often sound bad in poorly-encoded MP3s, because of harsh quantization in the frequency domain.

Finally, the coefficients are written out to a file as a stream of bits. Each file gets a huffman code allocated to it, which ideally is built from the distribution of quantized coefficient sizes seen in all of the blocks of an image. There are usually different encodings for luma and chroma, to reflect their different quantizations. Reading and writing this bitstream is a bit of a headache but the algorithm is specified in the JPEG standard, and all you have to do is implement it. Notably, though, there is special support for encoding a run of zero-valued coefficients, which happens often after quantization. There are rarely wavey bits in a blue blue sky.

on transforms

It's terribly common for photos to be wrongly oriented. Unfortunately, the way that many editors fix photo rotation is by setting a bit in the EXIF information of the JPEG. This is ineffectual, as web browsers don't look in the EXIF information, and silly, because it turns out you can losslessly rotate most JPEG images anyway.

Consider that the body of a JPEG is an array of macroblocks. To rotate an image, you just have to rearrange those macroblocks, then rearrange the blocks inside the macroblocks (e.g. swap the two Y' blocks in my above example), then transform the blocks themselves.

The lossless transformations that you can do on a block are transposition, vertical flipping, and horizontal flipping.

Transposition flips a block along its downward-sloping diagonal. To do so, you just swap the coefficients at (u, v) with the coefficients at (v, u). Easy peasey.

Flipping is trickier. Consider the enlarged DCT image from above. What would it take to horizontally flip the function at (0, 1)? Instead of going from light to dark, you want it to go from dark to light. Simple: you just negate the coefficients! But you only want to negate those coefficients that are "odd" in the X direction, which are those coefficients whose column is odd. And actually that's all there is to it. Flipping vertically is the same, but for coefficients whose row is odd.

I said "most images" above because those whose size is not evenly divided by the macroblock size can't be losslessly rotated -- you will end up seeing some of the hidden data that falls off the edge of the canvas. Oh well. Most raw images are properly dimensioned, and if you're downscaling, you already have to re-encode anyway.

But that's just flipping and transposition, you say! What about rotation? Well it turns out that you can express rotation in terms of these operations: rotating 90 degrees clockwise is just a transpose and a horizontal flip (in that order). Together, flipping horizontally, flipping vertically, and transposing form a group, in the same way that flipping and flopping form a group for mattresses. Yeah!

on scheme

I wrote this library in Scheme because that's my language of choice these days. I didn't run into any serious impedance mismatches; Guile has a generic multi-dimensional array facility that made it possible to express many of these operations as generic folds, unfolds, or maps over arrays. The huffman coding part was a bit irritating, but all in all things were pretty good. The speed is pretty bad, but I haven't optimized it at all, and it gives me a nice test case for the compiler. Anyway, it's been fun and it suits my needs. Check out the project page if you're interested. Yes, to shave a yak you have to get a bit bovine and smelly, but yaks live in awesome places!

Finally I will leave you with a glitch, one of many that I have produced over the last couple weeks. Comments and corrections welcome below. Happy hacking!

generators in firefox now twenty-two times faster

It's with great pleasure that I can announce that, thanks to Mozilla's Jan de Mooij, the new ES6 generator functions are twenty-two times faster in Firefox!

Some back-story, for the unawares. There's a new version of JavaScript coming, ECMAScript 6 (ES6). Among the new features that ES6 brings are generator functions: functions that can suspend. Firefox's JavaScript engine, SpiderMonkey, has had support for generators for many years, long before other engines. This support was upgraded to the new ES6 standard last year, thanks to sponsorship from Bloomberg, and was shipped out to users in Firefox 26.

The generators implementation in Firefox 26 was quite basic. As you probably know, modern JavaScript implementations have a number of tiered engines. In the case of SpiderMonkey there are three tiers: the interpreter, the baseline compiler, and the optimizing compiler. Code begins execution in the interpreter, which is the quickest engine to start. If a piece of code is hot -- meaning that lots of time is being spent there -- then it will "tier up" to the next level, where it is analyzed, possibly optimized, and then compiled to machine code.

Unfortunately, generators in SpiderMonkey have always been stuck at the lowest tier, the interpreter. This is because of SpiderMonkey's choice of implementation strategy for generators. Generators were implemented as "floating interpreter stack frames": heap-allocated objects whose shape was exactly the same as a stack frame in the interpreter. This had the advantage of being fairly cheap to implement in the beginning, but ultimately it made them unable to take advantage of JIT compilation, as JIT code runs on its own stack which has a different layout. The previous strategy also relied on trampolining through a helper written in C++ to resume generators, which killed optimization opportunities.

The solution was to represent suspended generator objects as snapshots of the state of a stack frame, instead of as stack frames themselves. In order for this to be efficient, last year we did a number of block scope optimizations to try and reduce the amount of state that a generator frame would have to restore. Finally, around March of this year we were at the point where we could refactor the interpreter to implement generators on the normal interpreter stack, with normal interpreter bytecodes, with the vision of being able to JIT-compile those bytecodes.

I ran out of time before I could land that patchset; although the patches were where we wanted to go, they actually caused generators to be even slower and so they languished in Bugzilla for a few more months. Sad monkey. It was with delight, then, that a month or so ago I saw that SpiderMonkey JIT maintainer Jan de Mooij was interested in picking up the patches. Since then he has been hacking off and on at getting my old patches into shape, and ended up applying them all.

He went further, optimizing stack frames to not reserve space for "aliased" locals (locals allocated on the scope chain), speeding up object literal creation in the baseline compiler and finally has implemented baseline JIT compilation for generators.

So, after all of that perf nargery, what's the upshot? Twenty-two times faster! In this microbenchmark:

function *g(n) {
    for (var i=0; i<n; i++)
        yield i;
}
function f() {
    var t = new Date();
    var it = g(1000000);
    for (var i=0; i<1000000; i++)
	it.next();
    print(new Date() - t);
}
f();

Before, it took SpiderMonkey 980 milliseconds to complete on Jan's machine. After? Only 43! It's actually marginally faster than V8 at this point, which has (temporarily, I think) regressed to 45 milliseconds on this test. Anyway. Competition is great and as a committer to both projects I find it very satisfactory to have good implementations on both sides.

As in V8, in SpiderMonkey generators cannot yet reach the highest tier of optimization. I'm somewhat skeptical that it's necessary, too, as you expect generators to suspend fairly frequently. That said, a yield point in a generator is, from the perspective of the optimizing compiler, not much different from a call site, in that it causes all locals to be saved. The difference is that locals may have unboxed representations, so we would have to box those values when saving the generator state, and unbox on restore.

Thanks to Bloomberg for funding the initial work, and big, big thanks to Mozilla's Jan de Mooij for picking up where we left off. Happy hacking with generators!

November 13, 2014

On GNOME and Groupon

You may have noticed that we ran a campaign calling for support regarding the Groupon trademark issue. Fortunately, everything was over much quicker than everybody expected.

It is fair to say that we were surprised by our campaign and the amount of support we had. And so were they (GroupOn). As Bradley said, the campaign could have failed miserably. It was a pure gamble. And I was everything but excited and full of expectations when we launched the campaign. We didn’t know how it would go and our preparation was.. simple, at best. I don’t mean to discredit any of the great work the volunteers around us (and we, ourselves) did. But it’s true that we’re not experts and that we didn’t have all the things in place you could have expected us to have. For example, we didn’t really have a bar of the money raised on the web page. In fact, that information was only available to a limited extent. It’s mainly my fault, but I also blame the fact that we only had mockups of the page, and not real code just until hours before the launch. Personally, my thinking was that we’d have days, if not weeks, to slowly fix things up.

Fortunately, things went differently. The coverage was amazing. I didn’t expect that our very simple page generated so much traffic. It’s hard to come up with an exact timeline of events as everything happened quickly and, in fairness, a bit chaotically. It may have been OMGUbuntu or Reddit who have reported first on our fundraiser. Other sites, such as Phoronix or Hackernews followed quickly. I was told that the latter was exceptional, because it ranked very high for rather long time.

We also had International coverage, i.e. on Heise (with somewhat interesting discussions), Golem (with two more articles!), Computerbase, and others… The usual suspects such as Slashdot, or, of course, LWN had an article as well. Even Arstechnica and Reuters covered our case. And that although we missed sending press releases to most of those sites. Sorry for that :-/

By quickly checking Google News, I know I haven’t found all the articles on the subject, but so far I’ve only found this article which was not in favour of our move. I think this was surprising to most, if not all of us.

Over the course of the day, this image was floating around, showing Brian’s LinkedIn profile which some people found hilarious. Some other pictures were floating around and comments were made. Some of them not in a not acceptable language but most of them were just expressing their concerns regarding Groupon’s behaviour. Some people cancelled all their accounts with Groupon while others started a petition.

We had close to one retweet per second and money was pouring in. The average amount donated was about 20 USD and the rate at which people donated was about 75 USD per minute. Every single minute. This can indeed be considered success. I think I noticed that this is going to be big when Freenode sent a message to all its 80000 connected users asking for supporting our case. “This is bigger than GNOME“, they said. Very correctly so. And it’s a shame, too. Not only for Groupon, because they needed to use the emergency break here, but for the system at large. It shouldn’t be the case that you need money in order to defend yourself against someone misusing your name.

timeline

Dear Internet, thanks. I am overwhelmed. We did not expect that amount of feedback to our recent trademark campaign, let alone the financial contributions. Our campaign was very successful. It was too successful, at least from a technical point of view. We are using a self made, very rudimentary Makefile for the business logic. We are still busy verifying the incoming transactions with Paypal… During the campaign, our servers were very busy handling the incoming requests.

I didn’t expect Groupon to be that cooperative given the behaviour I have observed over the last few months. It might have been Engagdet which were the first to report that Groupon backed up. Other news sites followed suit. All of that happened so quickly, that some news sites couldn’t even report on the case and could only report on Groupon abandoning their marks. That was probably Groupon’s strategy and, I guess, it was a wise choice. They retired their marks, but the app and their page are still online. They also still have a Gnome job posted. But I have no doubt that this will cease to exist.

Again: Thanks to everyone involved. This could as well have been the end to the GNOME Foundation, given that defending the GNOME marks is one of their main reasons for existing. A special thanks to all of you who have spread the word and made this campaign successful. Let’s hope we do not need such a campaign in the future.

For those of you who are interested in some pretty graphs (thanks benzo!), here is another one showing the transaction sizes and their volume. You can see, that we had many many small contributions. This is so amazing. I am very grateful and happy to see our community standing together so closely.

hist_10

Ducktype: A Lightweight Syntax for Mallard

One of the projects I’ve been working on lately is Ducktype, a lightweight syntax for Mallard. Mallard has a lot of strengths. Its automatic linking mechanisms make content organization easier. Its focus on independent topics makes content re-use possible. Its revision information and other metadata allow you to do status tracking on large content pools. It has a well-defined extension mechanism that allows you to add new functionality and embed external vocabularies like TTML, SVG, and ITS.

XML is the backbone that makes all of this possible. But XML is also what slows adoption. There’s a growing trend towards using lightweight formats to make it easier to contribute. But while lightweight formats make easy things easy, they tend to fall over when dealing with the issues that XML-based vocabularies are designed to solve.

The idea for a lightweight syntax for Mallard has floated around for a couple years. I even spent some time trying to repurpose an existing lightweight format like reStructuredText or AsciiDoc, but none of them are able to carry the level of semantic information that Mallard needs.

Before going into details, let’s look at a Mallard page written in Ducktype:

= My First Topic
@link[guide >index]
@desc A short description of this page
@revision[date=2014-11-13 status=draft]

This is the first paragraph.
The paragraph continues here, but ends with the blank line below.

[steps]
* This is a steps list, common in Mallard.
* Without the [steps] declaration above, we'd get a normal bullet list.
  Indentation is significant, so this is still in the second item.
* Indentation is so significant that you can actually nest block elements.

  So this is a new paragraph still inside the third item.

  [note]
  And this is a paragraph in a note in the third item.

* You can also nest list items, or literally anything else.

  * This is a basic bullet list.
  * It is in the fourth item of the steps list.

This paragraph is outside the steps list.

One of the most distinguishing features is that, like Python, indentation matters. Indentation is how you stay inside a block element. Ducktype also allows you to do everything you’d do inside a Mallard <info> element, which is crucial to pretty much all of the compelling features of Mallard.

Ducktype is guided by a few design principles, just as Mallard was so many years ago:

  1. It should be possible to do almost anything Mallard XML can do. You can arbitrarily nest block elements. You can have inline markup everywhere you need it, including in code blocks and in other inline markup. You can embed extensions and other vocabularies so that things like Mallard Conditionals and Mallard+TTML are possible. In fact, the only limitation I’ve yet encountered is that you can’t put attributes on page and section titles. This means that Ducktype is capable of serving as a non-XML syntax for virtually any XML vocabulary.
  2. The most commonly used Mallard features should be easy to use. Mallard pages tend to be short with rich content and a fair amount of metadata. Steps lists are common. Semantic inline content is common. Linking mechanisms are, unsurprisingly, extremely common. Credits are common. Revision info is common. Licenses are nearly always done with XInclude.
  3. There should be a minimal number of syntactical constructs. Most lightweight formats have shorthand, special-purpose syntax for everything. This makes it extremely difficult to support extension content without modifying the parser. And for any non-trivial content, it makes it difficult to remember which non-alphanumeric characters you have to escape when.
  4. For extra special bonus points, it should be possible to extend the syntax for special purposes. Lightweight syntaxes are popular in code comments for API documentation, and in API documentation you want shorthand syntax for the things you reference most often. For an object-oriented language, that’s classes and methods. For XSLT, it’s templates and parameters. By not gobbling up all the special characters in the core syntax, we make it possible to add shorthand inline notations by just loading a plugin into the parser.

There’s some discussion on the mallard-list mailing list, starting in August. And there’s a preliminary Ducktype parser up on Gitorious. You can also get it from PyPI with `pip install duck`. If you’re interested in docs, or ducks, or anything of the sort, please join the conversation. I always like getting more input.

BlinkOn 3

Last week I attended BlinkOn3 held at Google’s Mountain View office. Not only that but I also had the pleasure of giving a speech about what has been taking most of my time lately, the CSS Grid Layout implementation.

Although there were several talks already scheduled for some weeks, the conference itself is very dynamic in the sense that new talks were added as people started to propose new topics to discuss.

I found quite interesting the talks about the State of Blink and also the incoming changes related to Slimming Paint. Exciting times ahead!

My talk was about the CSS Grid Layout work Igalia has been carrying out for several months now (also thanks to Bloomberg sponsorship). The talk was very well received (we were not a lot of people mainly because my talk was rescheduled trice), and people in general is quite excited about the new opportunities for web authors the spec will bring.

The slides are here (3.3MB PDF). They look a bit blurry, that’s because its original format was the Google’s HTML5 io-2012-slides which allowed me to do a lot of live demos.

I also had the opportunity to talk to Julien Chaffraix about the next steps. We both are quite confident about the status of the implementation, so we decided to eventually send the “Intent to ship” at some point during Q4. Very good news for web authors! The most important things to address before the shipping are the handling of absolutely positioned items and a couple of issues related to grids with indefinite remaining space.

Xplain: Adding Transparency

The next article in my “Xplain” series is now complete and has been published: “Adding Transparency”. It’s an explanation of how exactly we added transparent windows to the X server, explaining the COMPOSITE X extension, along with other things like RENDER and TFP, together with live demos.

Any and all feedback welcome. I’m having a lot of fun doing these, and I recently got some downtime at work, so the next one might come even quicker than expected.

November 12, 2014

systemd For Administrators, Part XXI

Container Integration

Since a while containers have been one of the hot topics on Linux. Container managers such as libvirt-lxc, LXC or Docker are widely known and used these days. In this blog story I want to shed some light on systemd's integration points with container managers, to allow seamless management of services across container boundaries.

We'll focus on OS containers here, i.e. the case where an init system runs inside the container, and the container hence in most ways appears like an independent system of its own. Much of what I describe here is available on pretty much any container manager that implements the logic described here, including libvirt-lxc. However, to make things easy we'll focus on systemd-nspawn, the mini-container manager that is shipped with systemd itself. systemd-nspawn uses the same kernel interfaces as the other container managers, however is less flexible as it is designed to be a container manager that is as simple to use as possible and "just works", rather than trying to be a generic tool you can configure in every low-level detail. We use systemd-nspawn extensively when developing systemd.

Anyway, so let's get started with our run-through. Let's start by creating a Fedora container tree in a subdirectory:

# yum -y --releasever=20 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal

This downloads a minimal Fedora system and installs it in in /srv/mycontainer. This command line is Fedora-specific, but most distributions provide similar functionality in one way or another. The examples section in the systemd-nspawn(1) man page contains a list of the various command lines for other distribution.

We now have the new container installed, let's set an initial root password:

# systemd-nspawn -D /srv/mycontainer
Spawning container mycontainer on /srv/mycontainer
Press ^] three times within 1s to kill container.
-bash-4.2# passwd
Changing password for user root.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
-bash-4.2# ^D
Container mycontainer exited successfully.
#

We use systemd-nspawn here to get a shell in the container, and then use passwd to set the root password. After that the initial setup is done, hence let's boot it up and log in as root with our new password:

$ systemd-nspawn -D /srv/mycontainer -b
Spawning container mycontainer on /srv/mycontainer.
Press ^] three times within 1s to kill container.
systemd 208 running in system mode. (+PAM +LIBWRAP +AUDIT +SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ)
Detected virtualization 'systemd-nspawn'.

Welcome to Fedora 20 (Heisenbug)!

[  OK  ] Reached target Remote File Systems.
[  OK  ] Created slice Root Slice.
[  OK  ] Created slice User and Session Slice.
[  OK  ] Created slice System Slice.
[  OK  ] Created slice system-getty.slice.
[  OK  ] Reached target Slices.
[  OK  ] Listening on Delayed Shutdown Socket.
[  OK  ] Listening on /dev/initctl Compatibility Named Pipe.
[  OK  ] Listening on Journal Socket.
         Starting Journal Service...
[  OK  ] Started Journal Service.
[  OK  ] Reached target Paths.
         Mounting Debug File System...
         Mounting Configuration File System...
         Mounting FUSE Control File System...
         Starting Create static device nodes in /dev...
         Mounting POSIX Message Queue File System...
         Mounting Huge Pages File System...
[  OK  ] Reached target Encrypted Volumes.
[  OK  ] Reached target Swap.
         Mounting Temporary Directory...
         Starting Load/Save Random Seed...
[  OK  ] Mounted Configuration File System.
[  OK  ] Mounted FUSE Control File System.
[  OK  ] Mounted Temporary Directory.
[  OK  ] Mounted POSIX Message Queue File System.
[  OK  ] Mounted Debug File System.
[  OK  ] Mounted Huge Pages File System.
[  OK  ] Started Load/Save Random Seed.
[  OK  ] Started Create static device nodes in /dev.
[  OK  ] Reached target Local File Systems (Pre).
[  OK  ] Reached target Local File Systems.
         Starting Trigger Flushing of Journal to Persistent Storage...
         Starting Recreate Volatile Files and Directories...
[  OK  ] Started Recreate Volatile Files and Directories.
         Starting Update UTMP about System Reboot/Shutdown...
[  OK  ] Started Trigger Flushing of Journal to Persistent Storage.
[  OK  ] Started Update UTMP about System Reboot/Shutdown.
[  OK  ] Reached target System Initialization.
[  OK  ] Reached target Timers.
[  OK  ] Listening on D-Bus System Message Bus Socket.
[  OK  ] Reached target Sockets.
[  OK  ] Reached target Basic System.
         Starting Login Service...
         Starting Permit User Sessions...
         Starting D-Bus System Message Bus...
[  OK  ] Started D-Bus System Message Bus.
         Starting Cleanup of Temporary Directories...
[  OK  ] Started Cleanup of Temporary Directories.
[  OK  ] Started Permit User Sessions.
         Starting Console Getty...
[  OK  ] Started Console Getty.
[  OK  ] Reached target Login Prompts.
[  OK  ] Started Login Service.
[  OK  ] Reached target Multi-User System.
[  OK  ] Reached target Graphical Interface.

Fedora release 20 (Heisenbug)
Kernel 3.18.0-0.rc4.git0.1.fc22.x86_64 on an x86_64 (console)

mycontainer login: root
Password:
-bash-4.2#

Now we have everything ready to play around with the container integration of systemd. Let's have a look at the first tool, machinectl. When run without parameters it shows a list of all locally running containers:

$ machinectl
MACHINE                          CONTAINER SERVICE
mycontainer                      container nspawn

1 machines listed.

The "status" subcommand shows details about the container:

$ machinectl status mycontainer
mycontainer:
       Since: Mi 2014-11-12 16:47:19 CET; 51s ago
      Leader: 5374 (systemd)
     Service: nspawn; class container
        Root: /srv/mycontainer
     Address: 192.168.178.38
              10.36.6.162
              fd00::523f:56ff:fe00:4994
              fe80::523f:56ff:fe00:4994
          OS: Fedora 20 (Heisenbug)
        Unit: machine-mycontainer.scope
              ├─5374 /usr/lib/systemd/systemd
              └─system.slice
                ├─dbus.service
                │ └─5414 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-act...
                ├─systemd-journald.service
                │ └─5383 /usr/lib/systemd/systemd-journald
                ├─systemd-logind.service
                │ └─5411 /usr/lib/systemd/systemd-logind
                └─console-getty.service
                  └─5416 /sbin/agetty --noclear -s console 115200 38400 9600

With this we see some interesting information about the container, including its control group tree (with processes), IP addresses and root directory.

The "login" subcommand gets us a new login shell in the container:

# machinectl login mycontainer
Connected to container mycontainer. Press ^] three times within 1s to exit session.

Fedora release 20 (Heisenbug)
Kernel 3.18.0-0.rc4.git0.1.fc22.x86_64 on an x86_64 (pts/0)

mycontainer login:

The "reboot" subcommand reboots the container:

# machinectl reboot mycontainer

The "poweroff" subcommand powers the container off:

# machinectl poweroff mycontainer

So much about the machinectl tool. The tool knows a couple of more commands, please check the man page for details. Note again that even though we use systemd-nspawn as container manager here the concepts apply to any container manager that implements the logic described here, including libvirt-lxc for example.

machinectl is not the only tool that is useful in conjunction with containers. Many of systemd's own tools have been updated to explicitly support containers too! Let's try this (after starting the container up again first, repeating the systemd-nspawn command from above.):

# hostnamectl -M mycontainer set-hostname "wuff"

This uses hostnamectl(1) on the local container and sets its hostname.

Similar, many other tools have been updated for connecting to local containers. Here's systemctl(1)'s -M switch in action:

# systemctl -M mycontainer
UNIT                                 LOAD   ACTIVE SUB       DESCRIPTION
-.mount                              loaded active mounted   /
dev-hugepages.mount                  loaded active mounted   Huge Pages File System
dev-mqueue.mount                     loaded active mounted   POSIX Message Queue File System
proc-sys-kernel-random-boot_id.mount loaded active mounted   /proc/sys/kernel/random/boot_id
[...]
time-sync.target                     loaded active active    System Time Synchronized
timers.target                        loaded active active    Timers
systemd-tmpfiles-clean.timer         loaded active waiting   Daily Cleanup of Temporary Directories

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

49 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

As expected, this shows the list of active units on the specified container, not the host. (Output is shortened here, the blog story is already getting too long).

Let's use this to restart a service within our container:

# systemctl -M mycontainer restart systemd-resolved.service

systemctl has more container support though than just the -M switch. With the -r switch it shows the units running on the host, plus all units of all local, running containers:

# systemctl -r
UNIT                                        LOAD   ACTIVE SUB       DESCRIPTION
boot.automount                              loaded active waiting   EFI System Partition Automount
proc-sys-fs-binfmt_misc.automount           loaded active waiting   Arbitrary Executable File Formats File Syst
sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\x2dLVDS\x2d1-intel_backlight.device loaded active plugged   /sys/devices/pci0000:00/0000:00:02.0/drm/ca
[...]
timers.target                                                                                       loaded active active    Timers
mandb.timer                                                                                         loaded active waiting   Daily man-db cache update
systemd-tmpfiles-clean.timer                                                                        loaded active waiting   Daily Cleanup of Temporary Directories
mycontainer:-.mount                                                                                 loaded active mounted   /
mycontainer:dev-hugepages.mount                                                                     loaded active mounted   Huge Pages File System
mycontainer:dev-mqueue.mount                                                                        loaded active mounted   POSIX Message Queue File System
[...]
mycontainer:time-sync.target                                                                        loaded active active    System Time Synchronized
mycontainer:timers.target                                                                           loaded active active    Timers
mycontainer:systemd-tmpfiles-clean.timer                                                            loaded active waiting   Daily Cleanup of Temporary Directories

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

191 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

We can see here first the units of the host, then followed by the units of the one container we have currently running. The units of the containers are prefixed with the container name, and a colon (":"). (The output is shortened again for brevity's sake.)

The list-machines subcommand of systemctl shows a list of all running containers, inquiring the system managers within the containers about system state and health. More specifically it shows if containers are properly booted up, or if there are any failed services:

# systemctl list-machines
NAME         STATE   FAILED JOBS
delta (host) running      0    0
mycontainer  running      0    0
miau         degraded     1    0
waldi        running      0    0

4 machines listed.

To make things more interesting we have started two more containers in parallel. One of them has a failed service, which results in the machine state to be degraded.

Let's have a look at journalctl(1)'s container support. It too supports -M to show the logs of a specific container:

# journalctl -M mycontainer -n 8
Nov 12 16:51:13 wuff systemd[1]: Starting Graphical Interface.
Nov 12 16:51:13 wuff systemd[1]: Reached target Graphical Interface.
Nov 12 16:51:13 wuff systemd[1]: Starting Update UTMP about System Runlevel Changes...
Nov 12 16:51:13 wuff systemd[1]: Started Stop Read-Ahead Data Collection 10s After Completed Startup.
Nov 12 16:51:13 wuff systemd[1]: Started Update UTMP about System Runlevel Changes.
Nov 12 16:51:13 wuff systemd[1]: Startup finished in 399ms.
Nov 12 16:51:13 wuff sshd[35]: Server listening on 0.0.0.0 port 24.
Nov 12 16:51:13 wuff sshd[35]: Server listening on :: port 24.

However, it also supports -m to show the combined log stream of the host and all local containers:

# journalctl -m -e

(Let's skip the output here completely, I figure you can extrapolate how this looks.)

But it's not only systemd's own tools that understand container support these days, procps sports support for it, too:

# ps -eo pid,machine,args
 PID MACHINE                         COMMAND
   1 -                               /usr/lib/systemd/systemd --switched-root --system --deserialize 20
[...]
2915 -                               emacs contents/projects/containers.md
3403 -                               [kworker/u16:7]
3415 -                               [kworker/u16:9]
4501 -                               /usr/libexec/nm-vpnc-service
4519 -                               /usr/sbin/vpnc --non-inter --no-detach --pid-file /var/run/NetworkManager/nm-vpnc-bfda8671-f025-4812-a66b-362eb12e7f13.pid -
4749 -                               /usr/libexec/dconf-service
4980 -                               /usr/lib/systemd/systemd-resolved
5006 -                               /usr/lib64/firefox/firefox
5168 -                               [kworker/u16:0]
5192 -                               [kworker/u16:4]
5193 -                               [kworker/u16:5]
5497 -                               [kworker/u16:1]
5591 -                               [kworker/u16:8]
5711 -                               sudo -s
5715 -                               /bin/bash
5749 -                               /home/lennart/projects/systemd/systemd-nspawn -D /srv/mycontainer -b
5750 mycontainer                     /usr/lib/systemd/systemd
5799 mycontainer                     /usr/lib/systemd/systemd-journald
5862 mycontainer                     /usr/lib/systemd/systemd-logind
5863 mycontainer                     /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
5868 mycontainer                     /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt102
5871 mycontainer                     /usr/sbin/sshd -D
6527 mycontainer                     /usr/lib/systemd/systemd-resolved
[...]

This shows a process list (shortened). The second column shows the container a process belongs to. All processes shown with "-" belong to the host itself.

But it doesn't stop there. The new "sd-bus" D-Bus client library we have been preparing in the systemd/kdbus context knows containers too. While you use sd_bus_open_system() to connect to your local host's system bus sd_bus_open_system_container() may be used to connect to the system bus of any local container, so that you can execute bus methods on it.

sd-login.h and machined's bus interface provide a number of APIs to add container support to other programs too. They support enumeration of containers as well as retrieving the machine name from a PID and similar.

systemd-networkd also has support for containers. When run inside a container it will by default run a DHCP client and IPv4LL on any veth network interface named host0 (this interface is special under the logic described here). When run on the host networkd will by default provide a DHCP server and IPv4LL on veth network interface named ve- followed by a container name.

Let's have a look at one last facet of systemd's container integration: the hook-up with the name service switch. Recent systemd versions contain a new NSS module nss-mymachines that make the names of all local containers resolvable via gethostbyname() and getaddrinfo(). This only applies to containers that run within their own network namespace. With the systemd-nspawn command shown above the the container shares the network configuration with the host however; hence let's restart the container, this time with a virtual veth network link between host and container:

# machinectl poweroff mycontainer
# systemd-nspawn -D /srv/mycontainer --network-veth -b

Now, (assuming that networkd is used in the container and outside) we can already ping the container using its name, due to the simple magic of nss-mymachines:

# ping mycontainer
PING mycontainer (10.0.0.2) 56(84) bytes of data.
64 bytes from mycontainer (10.0.0.2): icmp_seq=1 ttl=64 time=0.124 ms
64 bytes from mycontainer (10.0.0.2): icmp_seq=2 ttl=64 time=0.078 ms

Of course, name resolution not only works with ping, it works with all other tools that use libc gethostbyname() or getaddrinfo() too, among them venerable ssh.

And this is pretty much all I want to cover for now. We briefly touched a variety of integration points, and there's a lot more still if you look closely. We are working on even more container integration all the time, so expect more new features in this area with every systemd release.

Note that the whole machine concept is actually not limited to containers, but covers VMs too to a certain degree. However, the integration is not as close, as access to a VM's internals is not as easy as for containers, as it usually requires a network transport instead of allowing direct syscall access.

Anyway, I hope this is useful. For further details, please have a look at the linked man pages and other documentation.

Microsoft Open Sources .NET and Mono

Today, Scott Guthrie announced that Microsoft is open sourcing .NET. This is a momentous occasion, and one that I have advocated for many years.

.NET is being open sourced under the MIT license. Not only is the code being released under this very permissive license, but Microsoft is providing a patent promise to ensure that .NET will get the adoption it deserves.

The code is being hosted at the .NET Foundation's github repository.

This patent promise addresses the historical concerns that the open source, Unix and free software communities have raised over the years.

.NET Components

There are three components being open sourced: the .NET Framework Libraries, .NET Core Framework Libraries and the RyuJit VM. More details below.

.NET Framework Class Libraries

These are the class libraries that power the .NET framework as it ships on windows. The ones that Mono has historically implemented in an open source fashion.

The code is available today from http://github.com/Microsoft/referencesource. Mono will be able to use as much a it wants from this project.

We have a project underway that already does this. We are replacing chunks of Mono code that was either incomplete, buggy, or not as fully featured as it should be with Microsoft's code.

We will be checking the code into github.com/mono by the end of the week (I am currently in NY celebrating :-)

Microsoft has stated that they do not currently plan on taking patches back or engaging into a full open source community style development of this code base, as the requirements for backwards compatibility on Windows are very high.

.NET Core

The .NET Core is a redesigned version of .NET that is based on the simplified version of the class libraries as well as a design that allows for .NET to be incorporated into applications.

Those of you familiar with the PCL 2.0 contract assemblies have a good idea of what these assemblies will look like.

This effort is being hosted at https://github.com/dotnet/corefx and is an effort where Microsoft will fully engage with the community to evolve, develop and improve the class libraries.

Today, they released the first few components to github; the plan is for the rest of the redesigned frameworks to be checked in here in the next few months.

Xamarin and the Mono project will be contributing to the efforts to bring .NET to Mac, Unix, Linux and other platforms. We will do this as Microsoft open sources more pieces of .NET Core, including RyuJIT.

Next Steps

Like we did in the past with .NET code that Microsoft open sourced, and like we did with Roslyn, we are going to be integrating this code into Mono and Xamarin's products.

Later this week, expect updated versions of the Mono project roadmap and a list of tasks that need to be completed to integrate the Microsoft .NET Framework code into Mono.

Longer term, we will make the Mono virtual machine support the new .NET Core deployment model as well as the new VM/class library interface

We are going to be moving the .NET Core discussions over to the .NET Foundation Forums.

With the Mono project, we have spent 14 years working on open source .NET. Having Microsoft release .NET and issue a patent covenant will ensure that we can all cooperate and build a more vibrant, richer, and larger .NET community.

November 11, 2014

Notes from the PulseAudio Mini Summit 2014

The third week of October was quite action-packed, with a whole bunch of conferences happening in Düsseldorf. The Linux audio developer community as well as the PulseAudio developers each had a whole day of discussions related to a wide range of topics. I’ll be summarising the events of the PulseAudio mini summit day here. The discussion was split into two parts, the first half of the day with just the current core developers and the latter half with members of the community participating as well.

I’d like to thank the Linux Foundation for sparing us a room to carry out these discussions — it’s fantastic that we are able to colocate such meetings with a bunch of other conferences, making it much easier than it would otherwise be for all of us to converge to a single place, hash out ideas, and generally have a good time in real life as well!

Incontrovertible proof that all our users are happy

Happy faces — incontrovertible proof that everyone loves PulseAudio!

With a whole day of discussions, this is clearly going to be a long post, so you might want to grab a coffee now. :)

Release plan

We have a few blockers for 6.0, and some pending patches to merge (mainly HSP support). Once this is done, we can proceed to our standard freeze → release candidate → stable process.

Build simplification for BlueZ HFP/HSP backends

For simplifying packaging, it would be nice to be able to build all the available BlueZ module backends in one shot. There wasn’t much opposition to this idea, and David (Henningsson) said he might look at this. (as I update this before posting, he already has)

srbchannel plans

We briefly discussed plans around the recently introduced shared ringbuffer channel code for communication between PulseAudio clients and the server. We talked about the performance benefits, and future plans such as direct communication between the client and server-side I/O threads.

Routing framework patches

Tanu (Kaskinen) has a long-standing set of patches to add a generic routing framework to PulseAudio, developed by notably Jaska Uimonen, Janos Kovacs, and other members of the Tizen IVI team. This work adds a set of new concepts that we’ve not been entirely comfortable merging into the core. To unblock these patches, it was agreed that doing this work in a module and using a protocol extension API would be more beneficial. (Tanu later did a demo of the CLI extensions that have been made for the new routing concepts)

module-device-manager

As a consequence of the discussion around the routing framework, David mentioned that he’d like to take forward Colin’s priority list work in the mean time. Based on our discussions, it looked like it would be possible to extend module-device-manager to make it port aware and get the kind functionality we want (the ability to have a priority-order list of devices). David was to look into this.

Module writing infrastructure

Relatedly, we discussed the need to export the PA internal headers to allow externally built modules. We agreed that this would be okay to have if it was made abundantly clear that this API would have absolutely no stability guarantees, and is mostly meant to simplify packaging for specialised distributions.

Which led us to the other bit of infrastructure required to write modules more easily — making our protocol extension mechanism more generic. Currently, we have a static list of protocol extensions in our core. Changing this requires exposing our pa_tagstruct structure as public API, which we haven’t done. If we don’t want to do that, then we would expose a generic “throw this blob across the protocol” mechanism and leave it to the module/library to take care of marshalling/unmarshalling.

Resampler quality evaluation

Alexander shared a number of his findings about resampler quality on PulseAudio, vs. those found on Windows and Mac OS. Some questions were asked about other parameters, such as relative CPU consumption, etc. There was also some discussion on how to try to carry this work to a conclusion, but no clear answer emerged.

It was also agreed on the basis of this work that support for libsamplerate and ffmpeg could be phased out after deprecation.

Addition of a “hi-fi” mode

The discussion came around to the possibility of having a mode where (if the hardware supports it), PulseAudio just plays out samples without resampling, conversion, etc. This has been brought up in the past for “audiophile” use cases where the card supports 88.2/96 kHZ and higher sample rates.

No objections were raised to having such a mode — I’d like to take this up at some point of time.

LFE channel module

Alexander has some code for filtering low frequencies for the LFE channel, currently as a virtual sink, that could eventually be integrated into the core.

rtkit

David raised a question about the current status of rtkit and whether it needs to exist, and if so, where. Lennart brought up the fact that rtkit currently does not work on systemd+cgroups based setups (I don’t seem to have why in my notes, and I don’t recall off the top of my head).

The conclusion of the discussion was that some alternate policy method for deciding RT privileges, possibly within systemd, would be needed, but for now rtkit should be used (and fixed!)

kdbus/memfd

Discussions came up about the possibility of using kdbus and/or memfd for the PulseAudio transport. This is interesting to me, there doesn’t seem to be an immediately clear benefit over our SHM mechanism in terms of performance, and some work to evaluate how this could be used, and what the benefit would be, needs to be done.

ALSA controls spanning multiple outputs

David has now submitted patches for controls that affect multiple outputs (such as “Headphone+LO”). These are currently being discussed.

Audio groups

Tanu would like to add code to support collecting audio streams into “audio groups” to apply collective policy to them. I am supposed to help review this, and Colin mentioned that module-stream-restore already uses similar concepts.

Stream and device objects

Tanu proposed the addition of new objects to represent streams and objects. There didn’t seem to be consensus on adding these, but there was agreement of a clear need to consolidate common code from sink-input/source-output and sink/source implementations. The idea was that having a common parent object for each pair might be one way to do this. I volunteered to help with this if someone’s taking it up.

Filter sinks

Alexander brough up the need for a filter API in PulseAudio, and this is something I really would like to have. I am supposed to sketch out an API (though implementing this is non-trivial and will likely take time).

Dynamic PCM for HDMI

David plans to see if we can use profile availability to help determine when an HDMI device is actually available.

Browser volumes

The usability of flat-volumes for browser use cases (where the volume of streams can be controlled programmatically) was discussed, and my patch to allow optional opt-out by a stream from participating in flat volumes came up. Tanu and I are to continue the discussion already on the mailing list to come up with a solution for this.

Handling bad rewinding code

Alexander raised concerns about the quality of rewinding code in some of our filter modules. The agreement was that we needed better documentation on handling rewinds, including how to explicitly not allow rewinds in a sink. The example virtual sink/source code also needs to be adjusted accordingly.

BlueZ native backend

Wim Taymans’ work on adding back HSP support to PulseAudio came up. Since the meeting, I’ve reviewed and merged this code with the change we want. Speaking to Luiz Augusto von Dentz from the BlueZ side, something we should also be able to add back is for PulseAudio to act as an HSP headset (using the same approach as for HSP gateway support).

Containers and PA

Takashi Iwai raised a question about what a good way to run PA in a container was. The suggestion was that a tunnel sink would likely be the best approach.

Common ALSA configuration

Based on discussion from the previous day at the Linux Audio mini-summit, I’m supposed to look at the possibility of consolidating the various mixer configuration formats we currently have to deal with (primarily UCM and its implementations, and Android’s XML format).

(thanks to Tanu, David and Peter for reviewing this)

Groupon Tried To Take GNOME's Name & Failed

[ I'm writing this last update to this post, which I posted at 15:55 US/Eastern on 2014-11-11, above the original post (and its other update), since the first text below is the most important message about this siutation. (Please note that I am merely a mundane GF member, and I don't speak for GF in any way.) ]

There is a lesson learned here, now that Groupon has (only after public admonishing from GNOME Foundation) decided to do what GNOME Foundation asked them for from the start. Specifically, I'd like to point out how it's all too common for for-profit companies to treat non-profit charities quite badly, even when the non-profit charity is involved in an endeavor that the for-profit company nominally “supports”.

The GNOME Foundation (GF) Board minutes are public; you can go and read them. If you do, you'll find that for many months, GF has been spending substantial time and resources to deal with this issue. They've begged Groupon to be reasonable, and Groupon refused. Then, GF (having at least a few politically savvy folks on their Board of Directors) decided they had to make the (correct) political next move and go public.

As a professional “Free Software politician”, I can tell you from personal experience that going public with a private dispute is always a gamble. It can backfire, and thus is almost always a “last hope” before the only other option: litigation. But, Groupon's aggressive stance and deceitful behavior seems to have left GF with little choice; I'd have done the same in GF's situation. Fortunately, the gamble paid off, and Groupon caved when they realized that GF would win — both in the court of public opinion and in a real court later.

However, this tells us something about the ethos of Groupon as a company: they are willing to waste the resources of a tiny non-profit charity (which is currently run exclusively by volunteers) simply because Groupon thought they could beat that charity down by outspending them. And, it's not as if it's a charity with a mission Groupon opposes — it's a charity operating in a space which Groupon claims to love.

I suppose I'm reacting so strongly to this because this is exactly the kind of manipulative behavior I see every day from GPL violators. The situations are quite analogous: a non-profit charity, standing up for a legal right of a group of volunteer Free Software developers, is viewed by that company like a bug the company can squash with their shoe. The company only gives up when they realize the bug won't die, and they'll just have to give up this time and let the bug live.

GF frankly and fortunately got off a little light. For my part, the companies (and their cronies) that oppose copyleft have called me a “copyright troll”, “guilty of criminal copyright abuse”, and also accused me of enforcing the GPL merely to “get rich” (even though my salary has been public since 1999 and is less than all of theirs). Based on my experience with GPL enforcement, I can assure you: Groupon had exactly two ways to go politically: either give up almost immediately once the dispute was public (which they did), or start attacking GF with dirty politics.

Having personally often faced the aforementioned “next political step” by the for-profit company in similar situations, I'm thankful that GF dodged that, and we now know that Groupon is unlikely to make dirty political attacks against GF as their next move. However, please don't misread this situation: Groupon didn't “do something nice just because GF asked them to”, as the Groupon press people are no doubt at this moment feeding the tech press for tomorrow's news cycle. The real story is: “Groupon stonewalled, wasting limited resources of a small non-profit for months, and gave up only when the non-profit politically outflanked them”.


My original post and update from earlier in the day on 2014-11-11 follows as they originally appeared:

It's probably been at least a decade, possibly more, since I saw a a proprietary software company attempt to take the name of an existing Free Software project. I'm very glad GNOME Foundation had the forethought to register their trademark, and I'm glad they're defending it.

It's important to note that names are really different from copyrights. I've been a regular critic of the patent and copyright systems, particularly as applied to software. However, trademarks, while the system has some serious flaws, has at its root a useful principle: people looking for stuff they really want shouldn't be confused by what they find. (I remember as a kid the first time I got a knock-off toy and I was quite frustrated and upset for being duped.) Trademark law is designed primarily to prevent the public from being duped.

Trademark is also designed to prevent a new actor in the marketplace from gaining advantage using the good name of an existing work. Of course, that's what Groupon is doing here, but Groupon's position seems to have come from the sleaziest of their attorneys and it's completely disingenuous Oh, we never heard of GNOME and we didn't even search the trademark database before filing. Meanwhile, now that you've contacted us, we're going to file a bunch more trademarks with your name in them. BTW, the odds that they are lying about never searching the USTPO database for GNOME are close to 100%. I have been involved with registration of many a trademark for a Free Software project: the first thing you do is search the trademark database. The USPTO even provides a public search engine for it!

Finally, GNOME's legal battle is not merely their own. Proprietary software companies always think they can bully Free Software projects. They figure Free Software just doesn't matter that much and doesn't have the resources to fight. Of course, one major flaw in the trademark system is that it is expensive (because of the substantial time investment needed by trademark experts) to fight an attack like this. Therefore, please donate to the GNOME Foundation to help them in this fight. This is part of a proxy war against all proprietary software companies that think they can walk all over a Free Software project. Thus, this issue relates to many others in our community. We have to show the wealthy companies that Free Software projects with limited resources are not pushovers, but non-profit charities like GNOME Foundation cannot do this without your help.

Update on 2014-11-11 at 12:23 US/Eastern: Groupon responded to the GNOME Foundation publicly on their “engineering” site. I wrote the following comment on that page and posted it, but of course they refused to allow me to post a comment0, so I've posted my comment here:

If you respected software freedom and the GNOME project, then you'd have already stop trying to use their good name (which was trademarked before your company was even founded) to market proprietary software. You say you'd be glad to look for another name; I suspect that was GNOME Foundation's first request to you, wasn't it? Are you saying the GNOME Foundation has never asked you to change the name of the product you've been calling GNOME?

Meanwhile, your comments about “open source” are suspect at best. Most technology companies these days have little choice but to interact in some ways with open source. I see of course, that Groupon has released a few tidbits of code, but your website is primarily proprietary software. (I notice, for example, a visit just to your welcome page at groupon.com attempts to install a huge amount of proprietary Javascript on my machine — lucky I use NoScript to reject it). Therefore, your argument that you “love open source” is quite dubious. Someone who loves open source doesn't just liberate a few tidbits of their code, they embrace it fully. To be accurate, you probably should have said: We like open source a little bit.

Finally, your statement, which is certainly well-drafted Orwellian marketing-speak, doesn't actually answer any of the points the GNOME Foundation raised with you. According to the GNOME Foundation, you were certainly communicating, but in the meantime you were dubiously registering more infringing trademarks with the USPTO. The only reasonable conclusion is that you used the communication to buy time to stab GNOME Foundation in the back further. I do a lot of work defending copyleft communities against companies that try to exploit and mistreat those communities, and yours are the exact types of manipulative tactics I often see in those negotiations.


0While it's of course standard procedure for website to refuse comments, I find it additionally disingenuous when a website looks like it accepts comments, but then refuses some. Obviously, I don't think trolls should be given a free pass to submit comments, but I rather like the solution of simply full disclosure: Groupon should disclose that they are screening some comments. This, BTW, is why I just use a third party application (pump.io) for my comments. Anyone can post. :)

Android: Changing action icon colors with Android 5.0’s drawable tinting

Android 5.0 (Lollipop), which is API version 21, supports tinting of drawables. So now you don’t need to recreate your monochrome action icons (in multiple sizes) just to show them in a different color in your app bar (ActionBar or ToolBar).

Unfortunately, drawable tinting isn’t available via the AppCompat library. That makes it useless for now unless you want to target only Android 5.0 devices, but here’s how to use it anyway. One day Android 5.0 might be old enough.

This is another part of my adventure in changing the color of stuff in Android’s app bar, after already figuring out how to change the color of the app bar’s text and standard icons.

Regular Drawables

Normally you’d just have the regular multiple .png files for your action item like so:

res/drawable-hdpi/ic_action_something.png
res/drawable-mdpi/ic_action_something.png
res/drawable-xhdpi/ic_action_something.png
res/drawable-xxhdpi/ic_action_something.png
res/drawable-xxxhdpi/ic_action_something.png

You would use these in your layout XML like so:

<item
    android:id="@+id/option_menu_item_something"
    android:icon="@drawable/ic_action_something"

Or you would use them in code like this:

menutem.setIcon(android.R.drawable.ic_action_something);

Tinted Drawables

You can now add a tinted version of the existing drawable like so:

res/drawable/ic_action_something_tinted.xml

With XML contents such as this:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_action_something"
    android:tint="@color/color_action_icons_tint"/>

That color_action_icons_tint could be hardcoded, but you’ll want to use the same one repeatedly via a color resource, like so:

res/values/color.xml

With XML contents like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="color_action_icons_tint">#5a6518</color>
</resources>

You can then refer to that tinted drawable just like any other drawable,

in your layout XML like so:

<item
    android:id="@+id/option_menu_item_something"
    android:icon="@drawable/ic_action_something_tined"

or in code like this:

menutem.setIcon(android.R.drawable.ic_action_something_tinted);

GNOME Trademark and Groupon

image from http://commons.wikimedia.org/wiki/File:Trademark-symbol.pngRegistered trademark

If you regularly read the minutes of the GNOME Foundation you noticed since few months there is a dispute about the use of the GNOME trademark by Groupon. The company has released a point of sale tablet under the name GNOME despite the trademark being registered by the GNOME Foundation.

So long story short, Groupon try now to steal the trademark GNOME and we need $80,000 to oppose the registration of the 10 first registrations of Groupon. All the details are at https://gnome.org/groupon/. So if you have some money to spend, consider giving some to defend the GNOME trademark to raise $80,000 by 8th December.

Spread the word on: Facebook, Google+ and Twitter

Update: It seems Groupon after months of request from the Foundation to change their product name, finally decided to accept this request after the dispute was made public. That’s a good move forward in right direction for us, but I want to see the registrations made from Groupon cancelled, and as suggested by someonee on twitter, I’d appreciate Groupon provide a donation to cover the money already involved in this legal process by the Foundation.

November 10, 2014

Yay, the left won! Or did it?

Originally published on politi.kov

I have been asked by a bunch of friends from outside of Brazil for my opinion regarding the recent elections we had in Brazil, and it is a bit complicated to explain it without some background, so I decided to write this piece providing a bit of history so that people can understand my opinion.

The elections this year were a rematch of our traditional polarization between the workers party (PT) and the social democracy party (PSDB), which has been going on since 1994. PT and PSDB used to be allies. In the 80s, when the dictatorship dropped the law that forbade more than 2 parties, the opposition party, MDB, began breaking up in several smaller ones.

PSDB was founded by politicians and intelectuals who were inspired by Europe’s social democracy and political systems. Parliamentarism, for instance, is one of the historical causes of the party. The workers party had a more grassroots origin, with union leaders, marxist intelectuals and marxist-inspired catholic priests being the main founders. They drew their inspiration from the USSR and Cuba, and were very close to social movements.

Lula and FHC campaigning together in 1981, by Clóvis Cranchi Sobrinho

Lula (PT) and FHC (PSDB) campaigning together in 1981, by Clóvis Cranchi Sobrinho

Some people have celebrated the reelection of Dilma Roussef as a victory of the left against the right. In my opinion that view is wrong for several reasons. First, because I disagree that PSDB and Aécio Neves in particular are right-wing, both in terms of economics and social/moral issues. Second, because I believe Dilma’s first government has taken a quite severe turn to the right in several topics that matter a lot to me. Since comparisons with PSDB’s government during the 90s has been one of the main strategies of the campaign this year, I’ll argue why I think it was actually a pretty good government with a lot of left in it.

Unlike what happens in most other places, Brazil does not really have an actual right-wing party, economics-wise. Although we might see the birth of a couple in the near future, no current party is really against public health, education and social security being provided by the state as rights, or wants to decrease state size and lower taxes significantly. It should come as no surprise that even though it has undergone a lot of liberal reforms over the last 20 years, Brazil is still a very closed country, with very high import tariffs and a huge presence of the state in the economy. There is a certain consensus about all of that, with disagreements being essentially on implementation details, not goals.

On the other hand, and contrary to popular belief, when it comes to social and moral issues we are a very conservative people. Ironically, the two parties which have been in power over the last 20 years are quite progressive, being historically proponents of diversity, minorities rights, reproductive rights. They have had to compromise on those causes to become viable alternatives, given the conservative nature of the majority of the voters.

Despite their different origins and beliefs, both parties share socialist inclinations and were allies from the onset. That changed in 1992, when president Collor, who had been elected on a runoff against Lula (who PSDB supported), was impeached by Congress for corruption. With no formal political support and a chaotic situation in his hands, Itamar Franco, the vice president, called for a “national union” government to go through the last two years of his term. PSDB answered the call, but the workers party decided against being part of the government.

Fernando Henrique Cardoso, a sociologist who was one of the leaders of PSDB was chosen to lead the Foreign Relations Ministry, but a few months later got nominated to the Economy. At the time, Brazil lived under hyperinflation of close to 1000% a year, and several stabilization plans had been attempted. Economy Ministers did not last very much in office at the time. FHC gathered a team of economists and sponsored their stabilization plan, which turned out to be highly successful: the Plano Real (“Real Plan”). In addition to introducing a new currency, something that was becoming pretty common to Brazilians by then, it also attacked the structural causes of inflation.

Lula was counting on the failure of the Plano Real when he ran against FHC in 1994, but the plan succeeded, giving FHC two terms as president. During those two terms, FHC introduced several institutional changes that made Brazil a saner country. In addition to the hyperinflation, Brazil had lived a debt crises for decades and was still in default. FHC’s team renegotiated the debts, reopened lines of credit, but most importantly, introduced reforms that made the Brazilian finances and financial system credible.

The problem was not even that Brazil had a fiscal déficit, it just did not have any control whatsoever of money supply and budget. Banks, regardless of whether they were private or public, had very little regulation and took advantage of the hyperinflation to hide monstrous holes in their balances. When inflation was gone and regulation became more strict, those became apparent, and it was pretty clear that the system would collapse if nothing was done.

Some people like to say that FHC was a president who ruled for the rich and didn’t care about the poor. I think the way the potential collapse of the banking system was handled is a great counter-example of that. The government passed laws that made the owners of the banks responsible for the financial problems, regardless of whether caused by mismanagement or fraud. If a bank went under, the central bank intervened and added enough money to protect the deposits, but that money was a loan that had to be repaid by the owners of the bank, and the owners’ properties were added as collateral to the loan. As a brazilian journalist once said, the people did not risk losing their deposits, the bankers did risk losing the banks, though. Today, we have a separate fund, filled with money from the banks, that does what the central bank did back then when required.

Compare that to countries where the banking system was saved with tax payer money and executives kept getting huge bonuses regardless, while owners kept their profits. It is hard to find an initiative that is more focused on the public interest against the interest of the rich people who caused the problem. This legislation, called PROER, is still in place today, and it came along with solid regulation of the banking system. It should come as no surprise that Brazil went through the financial crisis of 2008 with not a single hiccup of the banking system and no fear of bank runs. Despite having been against PROER back in the day, Lula celebrated its existence in 2008, when it was clear it was one of the reasons we would not suffer much. He even advertised it as something that should be adopted by the US and Europe.

It is also pretty common to hear that under FHC social questions were not a priority. I believe it is pretty simple to see that that was not the case both by inspecting the growth of social spending and the improvement of social indicators for the period, such as UN’s human development index. One area in which people are particularly critical of the FHC government is the investment on higher education, and they are actually quite right. Brazil has free Federal universities and those did not get a lot of priority in the 90s. However, I would argue that while it is a matter of priorities, it is not one of education versus something else, but rather of what to invest on inside education. The reality is basic education was the priority.

When FHC came to power, Brazil had a significant number of children who were not going to school at all. The goal was to make access to schools universal for young children, and that goal was reached. Every child has been going to school since the early 2000s, and that is a significant achievement which reaches the poorest. While the federal universities are attended essentially by the Brazilian elite, given the difficulty of passing the exams and the relative lack of quality of free public schools compared to private ones, which is still a reality to this day, investment on getting children to even go to school for the early years has a significant impact on the lives of the poorest.

It is important to remember that getting every child to go to school is also what gave birth to one of the most celebrated programs from the Lula era: Bolsa Família (“Family Allowance”) is a direct money transfer to poor families, particularly those who have children and has been an important contribution to lowering inequality and getting people out of extreme poverty. To get the money, the families need to ensure their children are 1) attending school and 2) getting vaccinated.

That program comes from the FHC government, in which it was created with the name Bolsa Escola (“School Allowance”), in its turn inspired by a program of the same name by governor Cristovam Buarque, from PT. What Lula did, and he deserves a lot of credit for this, was to merge a series of smaller programs with Bolsa Escola, and then expand the program to ensure it got to more and more people. Interestingly, during the announcement of the program he credited the idea of doing that to a state governor from PSDB. You can see why I think these two should be allies again.

When faced with all these arguments, people will eventually say that FHC was bad because he privatized companies and used orthodox economic policies. Well, if that is what it takes, then we’ll have to take Lula down with him, because his first term was essentially a continuation of FHC’s second term: orthodox economic policies to keep inflation down, along with privatization of several state-owned companies and banks. But Lula, whom I voted for and whose government I believe was a good one, is not my subject: Dilma is.

On Lula’s second term, Dilma gained a lot of power when other major leaders of PT went down for corruption. She became second in command and started leading several programs. A big believer in developmentalism, she started pushing for a bigger role of the state in the coordination of the productive sector, with a clear focus on growing the industrial base.

One of the initiatives she sponsored was a sizable increase on the number and size of subsidized loans given out by the national development bank (BNDES). Brazil started an unnofficial “national champions” program, where the government elected a few big companies to get a huge amount of subsidized credit.

The goal was for these selected firms to get big enough to be competitive on the global market. The criteria for the choices is completely opaque, if it even exists, and includes handing out milions in subsidized credit for Eike Batista, who became Brazil’s richest enterpreneur for a while, and lost pretty much everything when it became clear the oil would not be pumping out of his camps after all, sinking with them a huge amount of public funds invested by BNDES.

The way this policy was enacted, it is unclear how much it really costs in terms of public funds: the Brazilian treasury emits debt to capitalize, lends that money to BNDES with higher than market interest, and BNDES then lends it out to the big companies with a lower than market interest rate. Although it is obviously unsustainable, the problem does not yet show in the balance because the grace period for BNDES debt with the treasury is 2040. The fact that this has a cost and, perhaps more importantly, a huge opportunity cost is not clear because it is not part of the government budget. Why are we putting money in this rather than quadrupling Bolsa Família, which studies show generates 1,78 reais in GDP for every 1 real invested? Worse, why are we not even updating Bolsa Família enough to cover inflation?

When Dilma got elected in 2010, the first signs were pretty bad. She was already seen as someone who did not care much for the environment, and on her first month in power she made good on that promise by pushing to get the Belo Monte Dam building started as soon as possible regardless of conditionalities being satisfied. To this day there are several issues with how the building of the dam is going: the handling of the indigenous people and the small city nearby are lacking, conditionalities are not met.

Beyond Belo Monte, indigenous leaders are being assassinated, deforestation in the Amazon forest has increased by 122% in 2014 alone. Dilma’s answer to people who question her on these kinds of issues is essentially: “would you rather not have electric power?”

Her populist authoritarian nature and obsession with industry are also pretty evident when it comes to her policies in the energy area as a whole. She showed up in national tv on the eve of our independence day celebration to announce a reduction in electric tariffs, mainly for industry, but also for homes. Nobody really knew how. The following week she sent a fast-track project to Congress to automatically renew concessions of power grid operators, requiring those who accepted it to lower tariffs, instead of doing an auction, which was already necessary anyway because the concessions were up on 2015. There was no discussion with stakeholders, there was just a populist announcement and a great deal of rhethoric to paint anyone who opposed as being against the people.

And now, everything went into the crapper because that represented a breach of contract that required indemnification, and we had a pretty bad drought that made power more expensive given the need to turn on the thermal generators. Combining the costs of the thermal generation, indemnity, and financial fallout that the grid operators suffered, we are already at 105 billion reais and counting, nobody knows how high the cost will reach. Any reduction in tariffs has long been invalidated. And the fact that industry has lowered production significantly ends up being good news, we would probably be under rationing already if that was not the case.

You would expect someone who fought a dictatorship to be pretty good in terms of human and civil rights. What we see in reality is a lack of respect for those things. During the world cup, Dilma has put the army on the streets and has supported arbitrary behaviour from state polices throughout the country. They jailed a bunch of demonstrators preemptively. No shit. The would be demonstrators were kept in jail throghout the tournament under false accusations. Dilma’s Minister of Justice said several times that the case against them was solid and that the arrests were legal, but it turned out the case simply did not exist. Just this week we had a number of executions orchestrated by policemen in the state of Pará and there is zero reaction from the federal government.

In the oil industry, Dilma has enacted a policy of subsidizing gas prices by using a fixed price that used to be lower than the international prices (it is no longer the case with the fall in international prices). That would not be a problem if Brazil was selfsufficient in oild and gas, which we are not: we had to import a significant amount of both. The implicit subsidy cost Petrobrás a huge amount of cash – the more gas it sold, the bigger the losses. This lead not only to decreasing the company’s market value (it is a state-controlled, but open company), but to reducing its capacity of investment as well.

That is more problematic than it sounds because, with our current concession model, every single oil camp needs to have Petrobrás as a member of the consortium. Limiting the company’s investment capacity limits the rate at which our pre-salt oil camps can be explored and thus the speed at which we can become selfsufficient. Chicken and egg anyone?

To make things worse, Dilma has made policies that lowered taxes on car production, used to foster economic activity during the crisis in 2008-2010, essentially permanent. This lead to a significant increase in traffic and polution on Brazilian cities, while at the same time increasing the pressure on Petrobrás, which had to import more and more gas. Meanwhile, Brazilian cities suffer from a severe lack of mobility infrastructure. A recent study has shown that Brazil has spend almost twice as much subsidized money on pro-car policies than on pro-mass transit projects. Talk about good usage of public funds.

One of the only remaining good news the government was still able to mention was the constant reduction in extreme poverty. Dilma was actually ellected promising to erradicate extreme poverty and changed the government’s slogan to “A rich country is a country with no poverty” (País rico é país sem pobreza). Well, it turns out all of these policies caused inequality and extreme poverty both to stop falling as of 2013. And given the policies were actually deepened in 2014, I believe it is very likely we’ll see an increase in both when we get the data for 2014, next year.

Other than that, her policies ended up being a complete failure. Despite giving tax benefits to several sectors, investment has fallen, growth has fallen and inflation is quite high at 6,6% for the last 12 months. In terms of minorities, her government has been a severe set back, with the government going back on educational material against homophoby saying it would not do “advertisement of sexual choice”, and going back on a decree that allowed the public health system to perform abortions on the cases allowed by the law (essentially if the woman has been raped).

Looking at Dilma’s policies, I really can’t see that much of the left, honestly. So why, you might ask, has this victory been deemed a victory of the left over the right? My explanation is the aura the workers party still manages to keep over itself. There’s a notion that whatever PT does, it will still be more to the left than PSDB, which I think is just crazy.

There is also a fair amount of idealizing Dilma just because she is Lula’s protegé. People will forgive anything, provided it is the workers party doing it. Thankfully, the number of people aligned on the left that supported the candidate from PSDB this election tells me this is changing quite rapidly. Hopefully that leads to PT having to reinvent itself, and get in touch with the left again.

summing up 64

i am trying to build a jigsaw puzzle which has no lid and is missing half of the pieces. i am unable to show you what it will be, but i can show you some of the pieces and why they matter to me. if you are building a different puzzle, it is possible that these pieces won't mean much to you, maybe they won't fit or they won't fit yet. then again, these might just be the pieces you're looking for. this is summing up, please find previous editions here.

  • the collapse of complex business models, when ecosystems change and inflexible institutions collapse, their members disperse, abandoning old beliefs, trying new things, making their living in different ways than they used to. it's easy to see the ways in which collapse to simplicity wrecks the glories of old. but there is one compensating advantage for the people who escape the old system: when the ecosystem stops rewarding complexity, it is the people who figure out how to work simply in the present, rather than the people who mastered the complexities of the past, who get to say what happens in the future. recommended
  • notes on present status and future prospects, every new conceptual idea (unlike a mathematical one) must go through a phase of facing opposition from two sides - the entrenched establishment who thinks that its toes are being stepped on, and a lunatic fringe that springs up, seemingly by spontaneous generation, out of the idea itself. those whose fame and fortune are based on their very real accomplishments using previous methods have a strong vested interest in them and will raise strenuous opposition to any attempt to replace them. this phenomenon has been very well documented in many cases. in contrast to the establishment which is protecting something that has some demonstrated value, the lunatic fringe has no vested interest in anything because it is composed of those who have never made any useful contribution to any field. instead, they are parasites feeding on the new idea; while giving the appearance of opposing it, in fact they are deriving their sole sustenance from it, since they have no other agenda. the establishment and the lunatic fringe have the common feature that they do not understand the new idea, and attack it on philosophical grounds without making any attempt to learn its technical features so they might try it and see for themselves how it works. many will not even deign to examine the results which others have found using it; they know that it is wrong, whatever results it gives. there is no really effective way to deal with this kind of opposition; one can only continue quietly accumulating the evidence of new useful results, and eventually the truth will be recognized (pdf)
  • sequelitis - mega man classic vs. mega man x, games are supposed to be fun, and reading manuals isn't fun; it's pretty much the opposite of fun. but it is also true for software in general. manuals are pointless when we can learn about the game in the best and most natural way imaginable: by playing the actual game. you learn by doing, provided you have a well designed sandbox that lets you safely experiment as you're starting out in the game
  • trivial, the word "trivial" offers many opportunities to inappropriately reduce an item to its most basic components; allowing us to ignore the beauty that lies in the process. the value of a network is greater than the sum of its parts, but a simple misstep in vocabulary undermines it all
  • the fastest man on earth - the story of john paul stapp, stapp was promoted to the rank of major, reminded of the 18 g limit of human survivability, and told to discontinue tests above that level

Locally installing Phabricator on Fedora 20

Phabricator project logo

Uhm, no blog post for ages. Work and university kept me way busier (and less energetic to do much other things) than expected.

As announced in May 2014, Wikimedia will replace Bugzilla with Phabricator very soon for issue tracking. The Wikimedia Phabricator production instance is up and running and the migration from Bugzilla and RT is the next step on our migration timeline. A comparison between Bugzilla and Phabricator and documentation are available.

Time to publish my quick notes about installing Phabricator locally on a Fedora 20 machine. Maybe it’s useful for somebody, maybe not.

Phabricator’s official installation guide is pretty wonderful so I’ll only cover what I, being a simple user avoiding to think on his own and just blindly following guidelines, still had to do (which might be very obvious to tech-savvy users). I expect you to know that systemctl restart httpd.service, systemctl restart mysql.service and more /var/log/httpd/error_log are your friends.

  • First of all, I got the raw content of a php file displayed in my browser. Obviously I had to install the php package first. Heh.
  • Phabricator complained about the undefined function mysql_real_escape_string – the package php-mysqlnd was not installed.
  • The next and last problem not covered by documentation was Request parameter ‘__path__’ is set, but empty. Your rewrite rules are not configured correctly. The ‘__path__’ should always begin with a ‘/’. This required changing the corresponding RewriteRule in /etc/httpd/conf/httpd.conf to have a slash in front of $1.
  • Going to http://localhost.foo in your browser should now allow you to set up your admin account.
  • To get greeted with less “unresolved setup issues”: sudo yum install php-mbstring php-gd php-pecl-apcu.

In the end, my httpd.conf file looked like this:

<VirtualHost *>
  ServerName localhost.foo
  DocumentRoot /var/www/html/phab/phabricator/webroot
<Directory "/var/www/html/phab/phabricator/webroot">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>
  RewriteEngine on
  RewriteRule ^/rsrc/(.*)    -                       [L,QSA]
  RewriteRule ^/favicon.ico  -                       [L,QSA] 
  RewriteRule ^/(.*)$       /index.php?__path__=/$1  [B,L,QSA]
  ErrorLog /var/log/httpd/error_log
</VirtualHost>

November 08, 2014

Branding GNU Mailman Headers & Footers

As always, when something takes me a while to figure out, I try to post the generally useful technical information on my blog. For the new copyleft.org site, I've been trying to get all the pages branded properly with the header/footer. This was straightforward for ikiwiki (which hosts the main site), but I spent an hour searching around this morning for how to brand the GNU Mailman instance on lists.copyleft.org.

Ultimately, here's what I had to do to get everything branded, and I'm still not completely sure I found every spot. It seems that if someone wanted to make a useful patch to GNU Mailman, you could offer up a change that unifies the HTML templating and branding. In the meantime, at least for GNU Mailman 2.1.15 as found in Debian 7 (wheezy), here's what you have to do:

First, some of the branding details are handled in the Python code itself, so my first action was:

    # cd /var/lib/mailman/Mailman
    # cp -pa htmlformat.py /etc/mailman
    # ln -sf /etc/mailman/htmlformat.py htmlformat.py
  
I did this because htmlformat.py is not a file that the Debian package install for Mailman puts in /etc/mailman, and I wanted to keep track with etckeeper that I was modifying that file.

The primary modifications that I made to that file were in the MailmanLogo() method, to which I added a custom footer, and to Document.Format() method, to which I added a custom header (at least when not self.suppress_head). The suppress_head thing was a red flag that told me it was likely not enough merely to change these methods to get a custom header and footer on every page. I was right. Ultimately, I had to also change nearly all the HTML files in /etc/mailman/en/, each of which needed different changes based on what files they were, and there was no clear guideline. I guess I could have added <MM-Mailman-Footer> to every file that had a </BODY> but didn't have that yet to get my footer everywhere, but in the end, I custom-hacked the whole thing.

My full patches that I applied to all the mailman files is available on copyleft.org, in case you want to see how I did it.

November 07, 2014

GtkPopoverMenu – New widget for complex popovers

So, continuing my work on porting nautilus to gaction and gmenu, we found some problems that gtk+ could manage better.

For instance, creating menus with GMenu is very convenient only if your menu doesn’t have complex widgets like a GtkScale or if you want to really control how everything is displayed or you need to hide/show menu items on the fly.

That was the case of nautilus, which needs GtkScale and hide/show menu items on the fly.

So far I achieved a way to hide/show GMenu items on the fly, but it feels like a hack, so it was not very convenient.

After some discussion, Mathias Clasen created a new way to do complex popovers or menus, which is just a GtkWidget, so you are free for completely put and manage whatever you want in there, but with the advantatges of associating buttons to actions, so the button becomes a radio action, a simple item, or whatever based on the associated action.

Now we have a GtkPopoverMenu widget, which is the widget you have to use for associating directly to a button with gtk_menu_button_set_popover() and then, you have GtkModelButton which acts as a generic button which defines it’s looks based on the action associated and you can use it inside a GtkPopoverMenu. So for example, if you have a stateless action associated to a GtkModelButton, it becomes a single menu item, it the action is stateful and has no target, it becomes a check button, and finally if the action is stateful and has a target, it becomes a radio button.

Finally you can have iconic buttons, that is, buttons that looks like buttons ;) with <property name=”iconic”>True</property> .

Other widgets can’t have actions associated, like GtkScale, at least for now. But since you can put it in the widget, is not a big deal, and you connect to the change signal of the widget and then in the handler trigger the action you want, and then is like you associated an action to that widget.

So far so good, I ported nautilus to this, and it looks promising!

nautilus
So, my advice is:

Use GMenu always you can.

If you need buttons, that although they are supported in GMenu, you can’t manage its visuals; special widgets, or add/hide items on the fly; then, use GtkPopoverMenu and GtkModelButtons.

Not sure how this split is good or not, maybe we should find a common way to do things so new people are not confused about that. But for now, it’s a very nice solution.

Thanks Mathias for the work and the effort he put to find a solution for this.


November 05, 2014

Decade of Experience and some [un]wise words

This month, I complete working 10 years (6 months as an intern and 9.5 years as an employee) for Novell / SUSE / Attachmate / NetIQ India. During this time: I had some very good managers and some very bad managers; Worked with teams from multiple geographies (US, Germany, UK, Czech, Australia and of course India); Worked across multiple age groups (people who finished their PhDs before I was born to people who were born after the Matrix movie was released). The diversity was mainly due to the opensource nature of the work.

Here are some things that I have learned in the last 10 years. Some of them may apply to you. Some of them may not. Choose at your own will. If you are interested in becoming a [product|project] manager, the following may not be helpful, but if you intend to stay a developer, it may be useful.

  • In big companies, It is easier to do things and ask for excuse than to wait for permission, for trying radical changes or new things. There will always be people in the hierarchy to stop you from trying anything drastic, due to risk avoidance. Think how much performance benefits read-ahead gives; professional life is not much different. Do things without bothering about if your work will be released/approved.
  • Prototype a lot. What you cannot play around with in production/selling codebases, you can, in your own prototypes. Only when you play around enough, you will understand the nuances of the design.
  • Modern technologies get obsolete faster. People who knew just C program can still survive. But people who knew Angular 1.0 may not survive even Angular 2.0 Keep updating yourself if you want to be in the technology line for long
  • Do not become a blind fan of any technology / programming language / framework. There is no Panacea in software.
  • When one of my colleagues once asked a senior person for an advice, he suggested: "God gave you two ears and one mouth, use them proportionately". I second it, with an addendum, "Use your two eyes to read" also.
  • Grow the ability to zoom in and out to high/low levels as the situation demands. For example, you should know to choose between columnar or row based storage AND know about CPU branch prediction AND have the ability to switch to both of these depths at will, as the situation demands. Having a non-theoretical, working knowledge of all layers will make you a better programmer. There is even a fancy title for this quality, full-stack programmer.
  • Best way to know if you have learnt something well, is to teach it. Work with a *small* group of people with whom you can give techtalks and discuss your research interests. Remember the african proverb, If you want to go fast, go alone. If you want to go far, go together. Having a study groups helps a lot. But remember, talk is cheap and don't get sucked into becoming a theoretician. If you are interested in becoming one, get a job as a lecturer and work on hard problems. Look to Andy Tanenbaum or Eric Brewer for inspiration.
  • Keep a diary or blog of what you have learned. You can assess yourself on an yearly basis and improve yourself. Create and use your github account heavily.
  • Try different things and fail often. Failure is better than not-trying and being idle. When Rob Pike says, "I am not used to success", he is not merely being humble. It takes years of dedication, work, luck and a lot of failures to become successful and have a large / industry level impact.
  • Do not be driven too much by money or promotion or job titles. The world does not remember Alan Turing or Edsger Dijkstra or Dennis Ritchie by their bank balance or positions. There are probably a thousand software architects in your locality if you dig linkedin. Try to do good work. Also learn to think like an author.
  • Good work invariably will get appreciated, even if the appreciation may be delayed in many cases. Sloppy work will be noticed in the long term, even if it is missed in short term. The higher you grow, sloppy work may get more visibility.
  • There will be people smarter and more talented than you, always. Try to learn from them. Sometimes they may be younger than you. Don't let age stop you.
  • Work in an open source project with a very active community. Communication skills are very important even for an engineer. The best way to improve it for an engineer is to work on an open source project. Ideally, see through the full release of a linux distro. It will take you through all activities like packaging, programming, release management, marketing etc. the tasks which you may not be able to participate in your day job. I recommend openSUSE if you are looking for a suggestion ;)
  • Except for Mathematics and Music, there is no other field with prodigies. Understand the myth of genius programmer.
  • There are a lot of bad managers (at least in India). Most of these managers are bad at management, because they were lousy engineers in the first place and so decided to do an MBA and become a people manager, after which they don't have to code (at least in India). If you get one of them, do not try to fight them. Work with them on a monthly basis with a record of objectives and progresses. The sooner you get a bad manager, the better and faster you will appreciate good managers.
  • Last but not least, identify a very large, audacious problem and throw yourself at it fully. All the knowledge that you have accumulated over the years with constant prototyping and reading will come in handy while solving it. In addition, you will learn a thousand other things, which you could not have learned by lazily building knowledge by reading alone. But the goal that you need to work on has to be audacious (like the goals that gave us Google filesystem or AWS etc.) and solve a very big problem. However, you should start this only after a few years of building a lot of small things and have a full quiver. To become a good system-side programmer, you should have been a good userspace programmer. To become a good distributed systems developer, you should have used a distributed system, etc.  
May be one another point that I could add is: Try to write short and crisp (unlike this blog post).

November 04, 2014

Transmageddon Video Transcoder version 1.5 released

So just a quick update. I pushed out the 1.5 release of Transmageddon today. No major new features just fixing a regression in terms of dealing with files where you only have a video track or where you want to drop the audio track as part of the transcoding process. I am also having some issues with Intel Hardware encoding atm, but I think those are somewhere lower in the stack, so I hope to file a bug against either GStreamer or the libva project for that issue, but for now I recommend not having the Intel VA plugins for GStreamer installed.

As always you find the latest release on linuxrising.org.

I also submitted a Transmageddon update to Fedora 21, so if you are a Fedora user please test the build there and give it some Karma

I’m attending BlinkOn3

Today I’m giving a speech at BlinkOn3, the Blink contributors’ conference held in Google’s Mountain View Office. Check the agenda for further details.

The plan is to give an overview about the feature, present the most recent additions/improvements and also talk about the roadmap. My session is scheduled for 3:30PM at the Artic Ocean room. See you there!

UPDATE: we had many issues trying to setup the hangout so in the end we decided to move the session to Wednesday morning. It’s currently scheduled for 1:15PM just after lunch.

Simple macro for measuring algorithm's running time

Recently I'm spending a lot of time on my master's thesis. I'm working on algorithm for automatic number plates recognition using image segmentation. I'm trying to achieve high performance, so I need to measure execution time of my algorithms.
A few weeks ago I've written about google benchmark [1]. It's quite powerful library, and it's easy to use even in simple case, but sometimes we don't want to depend on an external library. So is it in my case too.
I've created simple macro for measuring running time:
#include <chrono>

#define MEASURE_TIME(unit, ...) \
[&] { \
using namespace std::chrono; \
auto start = high_resolution_clock::now (); \
__VA_ARGS__; \
auto time = high_resolution_clock::now () - start; \
return duration_cast<unit> (time).count (); \
} ();


Arguments:
  • unit - std::chrono::duration time interval. You can simply pass defined in standard library types, e.g. predefined types:
    • std::chrono::nanoseconds
    • std::chrono::microseconds
    • std::chrono::milliseconds
    • std::chrono::seconds
    • std::chrono::minutes
    • std::chrono::hours
  • ... - code for measurement
And example usage:
  int value = 0;

auto duration = MEASURE_TIME(std::chrono::milliseconds,
int arg0, arg1;
arg0 = run_time_consuming_algorithm ();
arg1 = run_another_one(arg0);
value = run_third_algorithm(arg1);
);

cout << "Execution time: " << duration << std::endl
<< "Computed value: " << value;

Note, that you can use earlier declared values (value variable, in my case), because all the values are captured by reference in lambda.

Feel free to use it ;)

Links
[1] http://cookandcommit.blogspot.com/2014/09/tiny-c-benchmark-framework_29.html 

Väldig bra (-:

11-04-intro

It was a pleasure to meet up with people and cats from the GNOME and FOSS community again. This time things took place in Gothenburg, Sweden. Good food, fun conversations, awesome pear cider and too much cheap candy. Most of FSCONS also went by with either staying around the GNOME booth or holding talks.

Thanks to Tobias we had a humungous amount of swag and sass for the GNOME booth. That event box and that box of t-shirts is heavy duty. I can easily imagine what trouble he must have had, bringing that all the way to FSCONS! With the booth set up and everything we quickly had GNOME 3.14 running for the curious folk to try. Most of my time at the booth was spent either showing off some of GNOME’s awesome features or talking about GNOME as a community.

11-04-gnome-boothSource: mozlib

FSCONS was also a great opportunity to meet other GNOMEers. I had a chat with both Jonas and Mathias who contribute to the Maps project. Sounded like there was some awesome things coming in the future and I might be contributing with some interaction design there too. It was also great to meet Andreas, Fabiana, Mimi and Zeeshan whom I stayed with during the conference.

11-04-gnome-people

Sometime during Saturday a person came over to me and asked me for an interview. It was Kenneth and I found out he was from “Hacker Public Radio”. So I spent 20 minutes answering questions related to a lighting talk I did about my student life as a linux user and the promotional videos I create. If you want to hear it, you might have to wait a month or two, though..

11-04-promotional-videos

Oh yes, and I did a workshop. One of the long ones. Sadly there was quite some turbulence in the FSCONS schedule during Sunday due to some very long lighting talks. After a bit of moving around I managed to get through it with an audience and everything, though. The workshop was about promotional videos. I focused on how you create them practically – the whole pipeline, what software you need to learn and why they can be important for your favorite free software project. Everything from this workshop is available online. The materials I have prepared include:

  • The slides themselves, explaining the process.
  • A set of video tutorials which covers the basics, if you want to create promotional videos the way I do.

You can download everything right here. It is also very likely that I will be holding this workshop again.

November 03, 2014

Tricks or Tracebacks? Pitivi 0.94 is here

Dear werepenguins, we’re thrilled to announce the immediate availability of Pitivi 0.94! This is the fourth release for the new version of our video editor based on GES, the GStreamer Editing Services library. Take a look at my previous blog post to understand in what context 0.94 has been brewing. This is mainly a maintenance release, but it does pack a few interesting improvements & features in addition to the bug fixes.

The first thing you will notice is that the main toolbar, menubar and titlebar have been replaced by a unified GTK HeaderBar, saving a ton of precious vertical space and making better use of the horizontal space. Once you try it, you can’t go back. There is beauty in the equilibrium it has now, compared to the previously clunky and unbalanced layout:

pitivi 0.94 headerbar comparison 1

Pitivi 0.93 on the left, 0.94 on the right

The combined screenshot above allows you to get the “complete picture” of how this change affects the main window, but it’s hard to get a sense of scale and it does not really do justice to the awesomeness of client-side decorations like the GTK HeaderBar. So here’s a simplified version where all the “wasted space” is highlighted in red:

pitivi 0.94 headerbar comparison 2

Pitivi 0.93 above, 0.94 below

Pretty rad, huh?

Beyond that eye-popping novelty, many distro/setup-dependent startup crashes have been investigated and fixed:

  • Various Linux distributions have started shipping a broken version of CoGL in recent months, which led to crashes. Technically this is a bug in the CoGL library/packaging, but we found out that the functions we were calling in that particular case were not needed for Pitivi, so we dropped our use of those broken CoGL APIs. Problem solved.
  • People running Pitivi outside of GNOME Shell were seeing crashes due to Clutter GStreamer video output, so we ported the viewer widget to use GStreamer’s new GL video output (glimagesink) instead of the ClutterSink. We had to fix various bugs in GStreamer’s glimagesink to raise it to the quality we needed, and our fixes have been integrated in GStreamer 1.4 (this is why we depend on that version). The GL image sink is expected to be a more future-proof solution.
  • We found issues related to gobject introspection or the overrides provided by gst-python. Again, make sure you have version 1.4 for things to work properly.
  • On avant-garde Linux distributions, you would get a TypeError traceback (“unsupported operand type(s) for /: ‘int’ and ‘NoneType”) preventing startup, which we investigated as bug 735529. This is now fixed in Pitivi.

We also have a collection of bug fixes to the way we handle the various resizeable & detachable components of the main window:

  • The default positioning of UI components (when starting from a fresh install) has been improved to be balanced properly
  • Undocked window components do not shift position on startup anymore
  • Docked window components do not shift position on startup anymore, when the window is not maximized. When the window is maximized, the issue remains (your help to investigate this problem is very much welcome, see bug 723061)

The title editor’s UI has been simplified and works much more reliably:

pitivi 0.94 title editor

Also:

  • Undo/redo should be globally working again; please file specific bug reports for the parts that don’t.
  • Pitivi has been ported to Python 3
  • The user manual is now up to date with the state of the new Pitivi series
  • Educational infobars throughout the UI have been tweaked to make their colors less intrusive
  • Various other fixes as usual. Testing and providing detailed reports for issues you encounter certainly helps!
  • There’s more. Find out in the release notes for 0.94!

This release is meant to be the last release based on our current “buggy stack”; indeed, as I mentioned in my previous status update, the next release (0.95) will run on top of a refined and incredibly more robust backend thanks to the work that Mathieu and Thibault have been doing to replace GNonLin by NLE (the new non-linear engine for GES) and fixing videomixing issues.

We recommend all 0.91/0.92/0.93 users to upgrade to this release. Until this trickles down into distributions, you can download our all-in-one bundle and try out 0.94, right here and now. Enjoy!

November 02, 2014

code churning and golang

Recently, we were doing a new prototype in dayjob. I had the freedom to choose the technology stack for this idea. I wrote a lot of golang code to compare a few aspects across few technologies (say streaming writes perf stats for Cassandra vs MariaDB etc.) to evaluate some of these technologies for our needs.

The whole activity spanned for about 12 weeks roughly and we were able to build a very good evolutionary prototype. I was looking at the gitlab stats at the end of 12 weeks and found my personal log to be:

9752 lines added
7119 lines deleted

Even if we assume a 6 day workweek, it translates to about 135 lines of new go code added per day by a developer on an average. There have been very productive days, where I was able to add more than 400 lines of non-copy-paste code in a single day, that I ended up having to take rest the next day, to recover.

In the past, I have written a lot of C code. I have never felt this productive in C, largely due to the manual memory management (and the ensuing problems like double free, leaks, valgrinding etc.) and difficult concurrency (pthreads, locks, etc.)

It is kind of obvious that Go will naturally feel more productive, due to automatic memory management and concurrency friendly features (goroutines, channels, etc.), resulting in very less non-business-code.

However, I observed that there are two other non-intuitive reasons why Go lang was very productive (for me). These reasons do not appear big on their own. But in the overall development time, they were a big influence on my productivity. They are:

1) Static Binary Creation without complex, external build tools

Thanks to my openSUSE packaging experience, I have always taken up the responsibility to keep the sources of the project where I work as an engineer, in a properly and a packager-friendly build system. I like build friendly sources to an extent that, about an year ago, One of the first tasks that I did, when I moved to a team, was to port an old packaging system of hand-written makefiles and obsolete build systems with sources across tens of thousands of files and managed for about two decades, to CMake. IOW, I know about Linux packaging and its pains.

With go, I was able to easily build the sources and get all the dependencies via a single `go get` command. Installing the binary on a test cluster, or in the AWS was merely a single command away. There was no need to wait for any complicated build setup, setting up dependencies or even waiting hours for a build to finish. There is no need to write complicated Makefiles, CMakeFiles, Configure files, build scripts etc.

Usage of the `go get` tool mandates developers to follow a certain discipline regarding installation/inclusion of libraries, binaries. Static binary generation helps avoid a tonne of deployment hassles. All these minor things, when we do a dozen or more builds in a day, add up to a very big productivity boost. It is not even that uncommon to do a dozen builds in a day, to aid testers, in the prototyping stage. Because of the elegance and simplicity of `go get`, the testers did not even have to wait on dedicated packagers or on developers to get the testbuilds. Even if you don't have dedicated testers, static binary generation, simplifies your test setup time.

2) Composition instead of Inheritance

This point is very difficult to explain, as it is more abstract, but is more influential than the previous. In the beginning, I was struggling to get Composition right. I ended up trying to organize my files based on an inheritance model (much like the [fs/< files>.c , fs/< ext>/, fs/< btrfs>/< files.c>] in the linux kernel), trying to get a baseclass delegating things to a derived class manually based on a derived class identifier in the object etc. I struggled and did not feel productive in coding.

I had to pause, unlearn a few things and think in a fresh perspective again to understand it. Composition is like Cycling. Once you get the hang of it, there is no falling down. I felt that the Composition based model has helped a lot more than any other feature of golang to improve my productivity.

With composition, the amount of code changes needed when you refactor code (which is very common in most freshly written code) is very very less than in a code, designed for inheritance. It is very hard to explain how this helps in simple English words. But I recommend you write code for yourself and appreciate this. In addition to easy refactoring, Composition tends to reduce boilerplate code substantially and makes diamond problem obsolete.

The Embedding of the Transport object in go lang's http Client object helped me understand Composition a lot clearer than any tutorial or book.

Conclusion

Because, I was able to write a lot of code fast, I was not too scared to shed code and start from scratch when needed. This explains the about 7k deletions of code.

goimports and vim-go also helped a lot to get some IDE like features, all of which should thank gofmt in return.

Have you felt any other reason that made you feel a high-level of code churning can be achieved in Go ?

November 01, 2014

Sound on bash command completion

I use the terminal a lot, usually with bash or fish shell, and I always wanted some kind of notification on command completion, especially for long-running greps or other commands.

The guys working on elementary OS have already implemented job completion notification for zsh shell in their pantheon-terminal project, but I wanted something more generic, working everywhere, even on the servers I am running commands through SSH.

The terminal bell sound is something I usually don't like, but it seemed like a good fit for a quick heads-up, so the Bell character came to the rescue.
As the bash prompt is fairly customizable, you can easily set a prompt which includes the magic BELL character.

In order to do this:
  • open a Terminal (surprize :))
  • run the command echo PS1=\$\'\x07\'\'$PS1\'
  • paste the output of the command into ~/.bashrc
Of course, this is not perfect, as it beeps for short commands too, not only long-running commands, but it works for me, maybe it will help you.

imgflo 0.2, The Grid launched

When I announced the first release of the imgflo project in April, it was perhaps difficult to see what exactly it was useful for and why we are developing it. This has changed now as 3 weeks ago we launched The Grid, our AI-based web publishing platform. We are on a bold mission to have “websites build themselves”; because until posting to personal websites becomes easier and more rewarding than posting to social media, content on the web will continue to pile up in closed silos.

thegrid-5k-join

To help solve this problem we built several open source technologies:

NoFlo: for creating highly testable, component-based, distributed software.
Flowhub: for visually and interactively building programs and extensions.
GSS: for building constraint-based, responsive layouts
And of course imgflo: for on-demand server-side image processing.

In total over 100k lines of code, and around 5000 commits over the last 12 months. Some of the stack is expained in more detail in a recent interview with Libre Graphics World.

imgflo on The Grid

thegrid.io launch site is of course built with The Grid. In the particular layout filter used, the look & feel is driven largely by the content. Colors for text captions are extracted from tweets and social media posts, and the featured images are largely unfiltered. Other Grid layout filters may style all provided content, including images, towards a uniform look specified by a color scheme. Or a layout filter may mix-and-match content- versus style-driven design.

The background texture on this section was created with imgflo, by passing the featured image through a blur graph:

thegridio-imgflo-bg-texture
https://imgflo.herokuapp.com/graph/vahj1ThiexotieMo/1ff47cef6f354fe0fbdefb…Fimages%2Fgrid-chrome.jpg&width=1300&height=768&std-dev-x=25&std-dev-y=25

It is important to note that no-one chose this exact image to be used in the particular layout section (and thus have the given image filter applied), which is why processing happens on-demand. The layout section with image inside a computer screen is available for content which has images of type “screenshot”. This property may be automatically detected by our image analytics pipeline, or manually annotated by user. The system allows describing many other such constraints, which are all taken into account when it works to create the appropriate layout for given content.

Even without considering styling, imgflo has a couple of important roles on a Grid site. Important is the ability create multiple scaled down versions to optimize download size. For this we also created a helper library called RIG, which is used to generate a set of CSS media-queries with imgflo request urls.


> rig = require 'rig-up'
> css = rig content, serverconfig, 'passthrough', parameters, ... 
 # passthrough is name of the graph to process through
 
@media (max-width: 503px) {
  .media, .background {
    background-image: url('https://imgflo.herokuapp.com/graph/apikey/6bb56129dc707894baa88d10a02a12b9/passthrough?input=https%3A%2F%2Fa.com%2Fb.png&width=400&height=225');
  }
}
@media (min-width: 504px) and (max-width: 1007px) {
  .media, .background {
    background-image: url('https://imgflo.herokuapp.com/graph/apikey/d099f7222293d335a6192d742f523bfa/passthrough?input=https%3A%2F%2Fa.com%2Fb.png&width=800&height=450');
  }
}

Processing images through imgflo also means that they are cached. So if the original image becomes unavailable, the website still has versions it can use. This can happen for instance on Twitter when people change their profile picture.
Note that while we optimize images when presented on site, we don’t touch the original image (non-destructive). This means image uploaded to The Grid has the full data & metadata preserved, unlike on some other social/web services. However, we are currently not preserving metadata in processed images.

 

imgflo 0.2

imgflo is now split into three repositories, the GEGL-based Flowhub runtime, the HTTP API server and the native dependencies. The runtime itself is plain C with glib, and could be used in non-web applications for desktop, mobile or embedded.

A major feature is that processing requests can now be authenticated, so that non-legitimate users cannot disrupt legitimate ones by overloading the server. We also use Amazon S3 for caching processed images, offloading a large portion of the work. Servicing 10k++ visits a day with a 2-dyno Heroko app has been no problem with this setup.

In imgflo-server we’ve also added support for using different processors than imgflo (which uses GEGL), in particular NoFlo with noflo-canvas. One can now build and deploy image processing pipelines using JavaScript, including all the libraries that work with the <canvas> element.

Building NoFlo image processing graph in Flowhub, then requesting from imgflo-server

Building NoFlo image processing graph in Flowhub, then requesting from imgflo-server

Full details about the changes can be found in the changelogs: server, runtime.

Scale

Flowhub provides imgflo a node-based visual & interactive IDE for developing new image filters for The Grid. It is similar to etablished tools like FilterForge, the Blender compositor,  vvvv and nuke – which many designers and visual artists are familiar with. However there are still many snags in the workflow for non-technical people. Smoothing out these is major part of the next imgflo milestone.
After that the focus will be on horizontal scalability, to handle the load as The Grid enters beta and opens to founding members in spring.

flattr this!

Hardware support news

Trackballs

I dusted off (literally) my Logitech Marble trackball to replace the Intuos tablet + mouse combination that I was using to cut down on the lateral movement of my right arm which led to back pains.

Not that you care about that one bit, but that meant that I needed a way to get a scroll wheel working with this scroll-wheel less trackball. That's now implemented in gnome-settings-daemon for GNOME 3.16. You'd run:


gsettings set org.gnome.settings-daemon.peripherals.trackball scroll-wheel-emulation-button 8

With "8" being the mouse button number to use to make the trackball ball into a wheel. We plan to add an interface to configure this in the Settings.

Touchscreens

Touchscreens are now switched off when the screensaver is on. This means you'll usually need to use one of the hardware buttons on tablets, or a mouse or keyboard on laptops to turn the screen back on.

Note that you'll need a kernel patch to avoid surprises when the touchscreen is re-enabled.

More touchscreens

The driver for the Goodix touchscreen found in the Onda v975w is now upstream as well.

October 31, 2014

Introduction to ICE and libnice

As part of the series of tea time talks we do within Collabora, I recently got to refresh my knowledge of STUN, TURN and ICE (the protocols for NAT traversal) and give an introductory talk on how they all fit together within the context of libnice.

Since the talk might be useful (and perhaps even interesting) to a wider audience, I’ve made it available: slides, handout and source (git). It’s under CC-BY-SA 4.0. Please leave comments if anything is unclear, incorrect, or could do with more in-depth coverage!

Recent improvements in libnice

For the past several months, Olivier Crête and I have been working on a project using libnice at Collabora, which is now coming to a close. Through the project we’ve managed to add a number of large, new features to libnice, and implement hundreds (no exaggeration) of cleanups and bug fixes. All of this work was done upstream, and is available in libnice 0.1.8, released recently! GLib has also gained a number of networking fixes, API additions and documentation improvements.

tl;dr: libnice now has a GIOStream implementation, support for scatter–gather send and receive, and more mature pseudo-TCP support — so its API should be much nicer to integrate; GLib has gained a number of fixes.

Firstly, what is libnice? It’s a GLib implementation of ICE, the standard protocol for NAT traversal. Briefly, NAT traversal is needed when two hosts want to communicate peer-to-peer in a network where there is at least one NAT translator between them, meaning that at least one of the hosts cannot directly address the other until a mapping is created in the NAT translator. This is a very common situation (due to the shortage of IPv4 addresses, and the consequence that most home routers act as NAT translators) and affects virtually all peer-to-peer communications. It’s well covered in the literature, and the rest of this post will assume a basic understanding of NAT and ICE, a topic about which I recently gave a talk.

Conceptually, libnice exists just to create a reliable (TCP-like) or unreliable (UDP-like) socket which connects your host with a remote one in a manner that traverses any intervening NATs. At its core, it is effectively an implementation of send(), recv(), and some ancillary functions to negotiate the ICE stream at startup time.

The biggest change is the addition of nice_agent_get_io_stream(), and the GIOStream subclass it returns. This allows reliable ICE streams to be used via GIOStream, with all the API sugar which comes with GIO streams — for example, g_output_stream_splice(). Unreliable (UDP-like) ICE streams can’t be used this way because they’re not technically streams.

Highly related, the original receive API has been augmented with scatter–gather support in the form of a recvmmsg()-like API: nice_agent_recv_messages(). Along with appropriate improvements to libnice’s underlying socket implementations (the most obscure of which are still to be plumbed in), this allows performance improvements by batching messages, reducing the number of system calls needed for communication. Furthermore (perhaps more importantly) it reduces memory copies when assembling and parsing packets, by allowing the packets to be split across multiple non-contiguous buffers. This is a well-studied and long-known performance technique in networking, and it’s nice that libnice now supports it.

So, if you have an ICE connection (stream 1 on agent, with 2 components) exchanging packets with 20B headers and variable-length payloads, instead of:

nice_agent_attach_recv (agent, 1, 1, main_context, recv_cb, NULL);
nice_agent_attach_recv (agent, 1, 2, main_context, recv_cb, NULL);

…

static void
recv_cb (NiceAgent *agent, guint stream_id, guint component_id,
         guint len, const gchar *buf, gpointer user_data)
{
    if (stream_id != 1 ||
        (component_id != 1 && component_id != 2)) {
        g_assert_not_reached ();
    }

    if (parse_header (buf)) {
        if (component_id == 1)
            parse_component1_data (buf + 20, len - 20);
        else
            parse_component2_data (buf + 20, len - 20);
    }
}

…

static void
send_to_component (guint component_id,
                   const gchar *data_buf, gsize data_len)
{
    gsize len = 20 + data_len;
    guint8 *buf = malloc (len);

    build_header (buf);
    memcpy (buf + 20, data, data_len);

    if (nice_agent_send (agent, 1, component_id,
                         len, buf) != len) {
        /* Handle the error */
    }
}

you can now do:

/* Only set up 1 NiceInputMessage as an illustration. */

static guint8 buf1_1[20];  /* header */
static guint8 buf1_2[1024];  /* payload size limit */
static GInputVector buffers1[2] = {
    { &buf1_1, sizeof (buf1_1) },  /* header */
    { &buf1_2, sizeof (buf1_2) },  /* payload */
};
static NiceInputMessage messages[1] = {
    buffers1, G_N_ELEMENTS (buffers1),
    NULL, 0
};
GError *error = NULL;

n_messages = nice_agent_recv_messages (agent, 1, 1, &messages,
                                       G_N_ELEMENTS (messages),
                                       NULL, &error);
if (n_messages == 0 || error != NULL) {
    /* Handle the EOS or error. */
    if (error != NULL)
        g_error ("Error: %s", error->message);
    return;
}

/* Component 2 can be handled similarly and code paths combined. */
for (i = 0; i &lt; n_messages; i++) {
    NiceInputMessage *message = &messages[i];

    if (parse_header (message->buffers[0].buffer)) {
        parse_component1_data (message->buffers[1].buffer,
                               message->buffers[1].size);
    }
}

…

static void
send_to_component (guint component_id, const gchar *data_buf,
                   gsize data_len)
{
    GError *error = NULL;
    guint8 header_buf[20];
    GOutputVector vec[2] = {
        { header_buf, sizeof (header_buf) },
        { data_buf, data_len },
    };
    NiceOutputMessage message = { vec, G_N_ELEMENTS (vec) };

    build_header (header_buf);

    if (nice_agent_send_messages_nonblocking (agent, 1, component_id,
                                              &message, 1, NULL,
                                              &error) != 1) {
        /* Handle the error */
        g_error ("Error: %s", error->message);
    }
}

libnice has also gained non-blocking variants of its I/O functions. Previously, one had to explicitly attach a libnice stream to a GMainContext to start receiving packets. Packets would be delivered individually via a callback function (set with nice_agent_attach_recv()), which was inefficient and made for awkward control flow. Now, the non-blocking I/O functions can be used with a custom GSource from g_pollable_input_stream_create_source() to allow for more flexible reception of packets using the more standard GLib pattern of attaching a GSource to the GMainContext and in its callback, calling g_pollable_input_stream_read_nonblocking() until all pending packets have been read. libnice’s internal timers (used for retransmit timeouts, etc.) are automatically added to the GMainContext passed into nice_agent_new() at construction time, which you must run all the time as before.

GIOStream *stream = nice_agent_get_io_stream (agent, 1, 1);
GInputStream *istream;
GPollableInputStream *pollable_istream;

istream = g_io_stream_get_input_stream (stream);
pollable_istream = G_POLLABLE_INPUT_STREAM ();

source = g_pollable_input_stream_create_source (pollable_istream, NULL);
g_source_set_callback (source, readable_cb, NULL, pollable_istream);
g_source_attach (main_context, source);

static gboolean
readable_cb (gpointer user_data)
{
    GPollableInputStream *pollable_istream = user_data;
    GError *error = NULL;
    guint8 buf[1024];  /* whatever the maximum packet size is */

    /* Read packets until the queue is empty. */
    while ( (len = g_pollable_input_stream_read_nonblocking (pollable_istream,
                                                             buf, sizeof (buf),
                                                             NULL,
                                                             &error) ) > 0) {
        /* Do something with the received packet. */
    }

    if (error != NULL) {
        /* Handle the error. */
    }
}

libnice also gained much-improved support for restarting individual streams using ICE restarts with the addition of nice_agent_restart_stream(), switching TURN relays with nice_agent_forget_relays(), plus a number of bug fixes.

Finally, FIN/ACK support has been added to libnice’s pseudo-TCP implementation. The code was originally based on Google’s libjingle pseudo-TCP, establishing a reliable connection over UDP by encapsulating TCP-like packets within UDP. This implemented the basics of TCP, but left things like the closing FIN/ACK handshake to higher-level protocols. Fine for Google, but not for our use case, so we added support for that. Furthermore, we needed to layer TLS over a pseudo-TCP connection using GTlsConnection, which required implementing half-duplex close support and fixing a few nasty leaks in GTlsConnection.

Thanks to the libnice community for testing out the changes, and thanks to the GLib developers for patiently reviewing the stream of tiny documentation fixes and several larger GLib patches! All of the libnice API changes are shown on the handy upstream-tracker.org tool.

Feeds