Older blog entries for cananian (starting at number 84)

Turtles All The Way Down

Inspired by Bert Freudenberg, Ian Piumarta, and Walter Bender, I started hacking on "Turtles All The Way Down" (aka TurtleScript) on the plane back from Uruguay. Now there's a nice rendering demo to show what a tile-based editor for JavaScript might look like, as well as a bytecode compiler and interpreter for the language. The bytecode instruction set is still too large; encouraged by Craig Chambers' work on SELF I think I ought to be able to replace all the unary and binary operators, conditional jumps, and slot selectors by a single mapof operator. I can put a better object model on the interpreter, too; I've written some notes on the matter.

The question is: does this really have educational value? "Turtles all the way down" is a great slogan, and a fine way to teach a graduate-level class on compiler technology, but I feel that the higher-level UI for tile-based program editing is the really useful thing for tablet computing. I'm a compiler geek and love the grungy underbelly of this stuff, but I keep reminding myself I should really be spending more time building a beautiful fluffy surface.

Syndicated 2011-05-20 06:06:15 from Dr. C. Scott Ananian

Next Steps for New Technologies

I've reached the end of the month. I've accomplished my Android and NativeClient-related goals, but didn't get the time to do as much mesh and python investigation as I'd wanted. Here are some ideas for next month's work. (Next week I'll be in Uruguay for EduJAM.)

GObject Introspection (Android or NaCl)

  1. Start by porting libffi. An android port would be straightforward, but since libffi involves code generation (ARM, x86), this is going to require a bit of assembly magic and the new "JIT"/"shared library" support in the NaCl plugin.
  2. Then port gobject-introspection. GObject-Introspection relies on libffi for its guts, but the hard part of this port will be refactoring g-i's build process, which is not cross-compilation friendly. Might need to rewrite some tools. If targeting NaCl, you might consider finishing the code allowing execution of unsandboxed NaCl binaries.
  3. Turn gobject-introspection on its head: generate GIR and a C binding for the platform "native" interface. For NaCl, this would be a GObject-using C-level binding of the browser-native DOM; for Android, this would be a GIR binding of the native Android APIs. These bindings should be mostly automatically generated, since they will need to continue tracking successive native platform releases/HTML5 features.
  4. Demos! Change browser DOM from Python, write native Android apps in Python. Add a gobject-introspection binding to cforth, then do the same from forth. (Forth might be a simpler place to start than Python. Or not.)

GTK (Android or NaCl)

  1. Build on the cairo/pango port to proceed to a full GTK backend for Android/NaCl. These backends ought to be upstreamable. The NaCl port should be based on the broadway work: the cairo canvas would be drawn to more directly, but a lot of the mechanism which captures JavaScript events and translates them into the GTK event loop could probably be reused.
  2. Demo: "Hello GTK world" in Android/NaCl.

Sugar partitioning.

Bring Sugar closer to being a true multi-language multi-library platform.

  1. Refactor sugar modules (for example, sugar toolbar widget) as standalone C libraries. Basic idea is to embed Python and export a C API, while preserving as much of the code as possible. Python libraries now invoke this library via g-i-r instead of directly. The python embedding tool is probably a useful standalone product.
  2. Rewrite "Hello, Sugar" activity in C (or vala), using #include for import and GObject inheritance instead of python inheritance. Use this as a guide to pull apart sugar into modules (as above) to make this code actually work as written.

Miscellanous topics

  1. ChromeOS w/ touch support.

    Find an appropriate machine, do an installation, what are the roadblocks/rough spots? Can we install on XO-1.75 as a testbed?

  2. TurtleArt as JavaScript viewer/editor.

    Revisit TurtleScript work, but skip over the time-consuming "construct an editor" step by reusing the (excellent) TurtleArt code.

  3. Mesh: android olsrd frontend, build testbed, research 802.11 DCF issues.

Summary

There are four rough topics here; I might try to continue the breadth-first search by spending a week on each. It might be more satisfying to downselect two of these issues and spend two weeks on each.

Syndicated 2011-04-29 15:47:57 from C. Scott Ananian

Pango/Android -vs- Pango/NaCl

At the end of my Sugar/Android week, I had a simple Pango-on-Cairo demo running. This was built on a stack of ported libraries, including gettext, pixman, freetype, libxml2, fontconfig, and glib, as well as cairo and pango. You can run the demo yourself by sideloading pango-demo.apk onto your Android device (tested on a Motorola Xoom), and you can browse the source code to see what it entailed (here's the scariest part). (I was inspired by Akita Noek's android-cairo project, but I ended up reworking the build scheme and redoing most of the ports.)

Screenshot of Pango demo on Android

It made sense to start my Sugar/NaCl investigation by porting the same demo application to Native Client. The same stack of ported libraries was involved, although it was easy to include more functionality in the Native Client ports, including threading and PNG/PS/PDF support in cairo. The source code is a fork from the upstream naclports project, and the process was generally much cleaner. (But see my previous post for some caveats regarding naclports.) If you're using Chrome 10 or 11, you can run the demo in your browser (follow the instructions on that page). The Wesnoth team has a parallel project which ported some of these libraries as well, but not in an upstreamable manner.

Screenshot of Pango demo on Native Client

The demo app uses cairo to draw the background, an animated X, and some basic text in the center; it uses Pango's advanced international text support to draw properly-shaped Persian text in a circle around it. The center text is the "proper" bilingual Greek/Japanese written form of "pango"; the text around the edges is the Persian name of the internationalization library, "harfbuzz". Note that the Persian text is written right-to-left—and that I didn't put a full CJK font in the NaCl app, so the Japanese "go" character is missing. The Android port rebuilds the font cache at each startup, so it loads rather slowly; the NaCl port contains a prebuilt font cache so it starts more quickly.

Both ports took about two weeks. I blew my original schedule, partly due to the Patriot's day holiday, and partly because I'd given Android about a week's head start by tinkering on it before my original schedule post. The framerate of the demo is much better on NaCl (so fast that the edges of the animated X look choppy in the screenshot), but the hardware isn't easily comparable, so the comparison doesn't really tell us much. The porting effort was certainly more pleasant on NaCl, since newlib is a much more complete libc than Android's "Bionic"—but having gdb available made debugging on Android easier. (There is an unintegrated NaCl branch that integrates NaCl gdb in the browser, though!)

Much of the GNOME/POSIX library stack assumes access to a filesystem tree and does file-based configuration. In our demo application, fontconfig was the most culpable party: it wanted to load a configuration file describing font locations and naming, then to load the fonts themselves from the file system, and finally to write a cache file describing what it found back to the file system. Most ported software is going to want similar access—even if you store the user's own documents in a Journal, software still expects to find configuration, caches, and other data in a filesystem.

Android provides the POSIX filesystem APIs, but the filesystem an app can touch is segmented and sandboxed. As discussed previously, Android's Opaque Binary Blob feature may allow you to create a app-specific filesystem, but this doesn't let you share (for example) fonts and font configuration between activities. NaCl might eventually provide a similar unshared mechanism based on the HTML5 AppCache.

The preferred solution is more limited, but more flexible: no built-in filesystem APIs are used (or in NaCl's case, provided!) at all. Instead, you provide your own implementation of the POSIX file APIs (either via the --wrap linker indirection or through an appropriate backend to newlib/glibc/glib). For the NaCl demo app, I wrote a rather-elaborate in-memory filesystem --- only to find that an even-more-elaborate one already existed in naclports. But the longer-term solution uses message-passing (SRPC in NaCl, intents in Android) to implement these POSIX APIs. In Native Client, the implementation would be in browser-side JavaScript, which would then allow you to share parts of the filesystem tree between activities and/or map it into (cached) web-addressed resources. In either case, your application still sees the bog-standard POSIX API it expects.

More problematic are the networking APIs. Here Android provides a pretty standard socket library, while Native Client provides nothing at all. Using a browser-based implementation, as for the file APIs, will work fine for HTTP, WebSockets and even P2P via the HTML5 P2P APIs. But it's not clear that (for example) glib's elaborate asynchronous DNS name resolver implementation can (or should!) be implemented in a NaCl port.

In the end, the porting effort and abstraction shifts needed for Native Client and Android are roughly comparable. I expect Native Client will hold a strong edge in allowing close integration with web standards and web technologies. Android will probably continue to hold an edge in third-party application support and platform maturity.

Syndicated 2011-04-29 15:08:56 from C. Scott Ananian

Sugar-on-Native Client investigation

This post will describe the state of Native Client in general, based on week 2 of my original four week plan. In the next post, I'll link to my work so far, and compare the Native Client and the Android efforts. Recapping, the end goal of these explorations is a platform for the next generation of the Sugar learning environment.

To begin, the Native Client (NaCl) plugin is fairly mature in a number of areas. Version 0.2 of the NaCl SDK was recently released (a version number which substantiates the "fairly" in my previous sentence), and the NativeClient plugin is currently shipping in Chrome (versions 10 and 11), although you have to manually turn on a preference in the about:flags dialog to enable it. The NaCl toolchain is much more standard than the Android NDK toolchain I discussed previously, and the robust naclports tree shows that the patches required for NaCl ports of common packages tend not to be too evil. The Tcl interpreter and Qt tookit port demos show that fairly complex pieces of code can be deployed today on NaCl.

On the other hand, there are three main difficulties:

  1. The default NaCl toolchain uses newlib as its standard C library. This is consistent with Google's preference for BSD-licensed code in SDKs they provide to the public (see the discussion of Bionic in the Android SDK). However, there also exists a branch of the SDK which uses glibc. The glibc branch supports several additional features, like shared library support. However, it is unclear whether this will ever be a "supported" part of the SDK. If glibc does become supported, it is unlikely ever to be the only supported libc; the BSD-licensed newlib will need to remain available as an option. (Yes, the LGPL license of glibc shouldn't inspire such paranoia, but Google has elected not to undertake the education of all prospective third-party developers.)
  2. The naclports project, although fairly robust, is driven between the Scylla and Charybdis of compatibility. The goal is that all the code in naclports be buildable at all times on all three major platforms: Windows, Mac, and Linux. Further, it should support both x86_32 and x86_64 backends, and ideally ARM and pNaCl as well. It's auto-built against the latest SDK sources, but should also work on the latest released SDK. And with the addition of the glibc/newlib split discussed above, the possible build targets are multiplied further. Needless to say, keeping the tree building against such a large number of variants is not an easy task, and naclports is usually broken in some way. In practice, most developers seem to pay attention to some subset (say, x86_32/newlib/Linux host), but it's hard to push patches upstream without worrying about breaking some obscure target. It might be best to base future work on a proper package technology, like (say) dpkg-cross.
  3. In general, a lot of interesting NaCl development has occurred on branches that are not easily integrated. I've already mentioned glibc support, which is a toolchain branch; shared library support is on another branch that requires a new chromium plugin as well. At various times different means have been implemented to run NaCl binaries "natively" outside the sandbox (for example, in order to test some feature at build time, or auto-generate some piece of code via introspection). These efforts live on abandoned branches, while the "official" means to do this is incomplete. Similarly, a lot of interesting NaCl work used the now-abandoned legacy "NPAPI" plugin interface to interact with the browser. It was followed by the "Pepper" plugin interface, which was itself abandoned. Current work uses the Pepper2 browser plugin APIs, which (unfortunately) have not yet been implemented in non-Chrome browsers and continue to flux about. Many interesting browser interactions exist only in deprecated Pepper APIs, not having yet been built into Pepper2. ARM and pNaCl work also appears to be on unintegrated branches. There are a number of different gdb support strategies.

None of these difficulties is insurmountable—and in fact, some are side-effects of the desirable active development and productization of Native Client. To date I've done my work on the (more compatible) SDK v0.1 and the (more upstreamable) newlib library. So far newlib has not been a huge obstacle, and this basis allows my patches and ports to be more broadly useful. This might change in the future—certainly at some point we need to move to ARM and/or pNaCl for XO-3, which will probably require building chrome and the NaCl toolchain from scratch. At that point, it may be worth further exploring the non-mainstream branches.

Syndicated 2011-04-29 14:24:36 (Updated 2011-04-29 16:43:48) from C. Scott Ananian

How does the iPad "use the iPhone's GPS"?

A few months ago, a number of stories came out covering the iPad's remarkable-seeming ability to share the GPS of a tethered iPhone. Apple's latest location database FAQ confirms the suspicions I voiced at the time: there's no actual GPS sharing involved. Instead, Apple is using the simultaneous GPS and Wifi radios on your iPhone to "crowd-source" what I'll call a "skyhook" database (after the first company to publicly use the technique). This correlates Wifi base station identifiers with their GPS locations in real time -- including (most likely) the real time location of the "base station" created by the iPhone when it is in tethering mode. All nearby Apple devices use this database to compute their location (based on all visible wifi base stations). Since the nearby device sees the iPhone's "base station" and the iPhone is busily updating the position of that "base station" in real time (along with all the other base stations the iPhone can see), the iPad (lacking a GPS of its own) gains the apparent magical ability to compute a very accurate position for itself.

The real interesting part of this story involves user consent and privacy—do iPhone users generally know that their devices are registering their location in Apple's database in real time whenever tethering is turned on? Any device which can query Apple's location database for the MAC address of your iPhone can track the position of your iPhone whenever you are tethering. That's basically what the magical ability of the iPad/iPhone pair tells us. Did you know that?

Syndicated 2011-04-27 18:30:23 (Updated 2011-04-27 18:30:50) from C. Scott Ananian

Sugar-on-Android, week one

Last week I described a four-week plan to survey key technologies for One Laptop Per Child's forthcoming XO-3 tablet computer. Here I'll describe the results of the first week of work, which dove into Google's Android operating system. Warning: technical content ahead...

Basic design of Sugar-on-Android

  1. Cross-compile gobject/GTK/gobject-introspection/cairo/dbus for Android; distribute these key libraries as NDK libraries. This is what I spent most of my time on this week: I've managed so far to port libiconv, gettext, glib, pixman, freetype, fontconfig, cairo, libxml2, and pango. (Source code)
  2. Use cairo or OpenGL backends of GTK3 to render legacy Sugar activities directly to Android canvas.
  3. Modularize sugar; use D-Bus for inter-module communication. Interprocess communication mechanism is Android 'intents'; these can redirect to the web or the Android Market for missing dependencies. (Collabora reportedly already has a D-Bus implementation for Android.) Sugar components can also become Android Services.
  4. Implement Sugar Home/Groups/Neighborhood views and Journal as four separate Android App Widgets. These could also be implemented by providing a new Android home application, but I think the finer-grained modularity afforded by splitting these functions would yield a better design and make it easier to incorporate upstream improvements to the Android launcher.(Android Live Wallpaper is also similar in function, but not as good a fit.)
  5. The Sugar Journal becomes an Android "Content Provider", which stores/retrieves content for other Sugar activities. (There is special Android support for "collection-based Widgets" and Live Folders which may be helpful.)
  6. Use gobject-introspection to build a multi-language environment. Use JGIR to expose Sugar APIs to "native" Dalvik apps; use something like the Android Scripting Environment to expose Android native APIs to GIR languages (Python, JavaScript, C, etc).
  7. [opportunity] Use the Android port of OLSRd to implement a Neighborhood view. Alternatively, investigate AODV routing on Android and/or AllJoyn (which also requires root access, see pg 24-25 of the manual).

Key Benefits

  • Sugar is integrated into Android environment; use native Android education apps, or apps like Movie Studio which have no Sugar equivalents yet.
  • Android APIs and customization hooks are good, and provide a more-extensible framework for development.

Open challenges (general)

  1. The web integration story is cloudy. Java and JavaScript can call each other inside a bundled WebView widget, but this isn't supported in standard Browser app. Browser plugin interface would help.
  2. No good story for building 'native' Java/Dalvik or C apps on the device. Writing a simple Dalvik compiler would help. Dalvik specs are available, and people have written Dalvik compilers for toy languages.
  3. "View source" requests can be implemented as an Android 'intent' message, but no good story for implementing this functionality other than on a case-by-case basis in each activity.
  4. Although the Amazon Marketplace for Android indicates that it can be done, it appears that there is no "blessed" mechanism for creating .apk files on the device and installing them. (Android bug, discussion)

Current technical issues/bugs

  1. Cross-compiling for Android is currently a miserable experience. The Android NDK appears to have been put together by a team which had never seen a proper cross-compiler before. Since I only had a week for this exploration, I mostly kludged things together to get past this, but any serious work with Android should start by defining and upstreaming proper autoconf "target triplets" for Android-on-{ARMv5, ARMv7, x86} and building a proper cross-compiler. Then patches to various tools and libraries could start being upstreamed. Using the bespoke Android.mk build system of the NDK is a non-starter. No serious obstacles here, just work to do.
  2. Xoom hardware is ARMv7, but Android emulator is ARMv5 only. Unfortunately, gdb is broken on the Xoom. So we're building for ARMv5 at the moment, so we can debug in the (slow) emulator.
  3. No good support for shared libraries may cause activity bloat. May be able to be worked around using the new Opaque Binary Blob (OBB) feature.
  4. Much existing code (fontconfig, gettext, gtk, etc) expects to read configuration files from the filesystem. Currently we are using the default fall-back configurations. OBB support may help here as well. There are a number of different storage APIs in Android, but none seems quite right.
  5. It would be nice to implement a ring-style XO home screen without completing replacing the android Launcher. No clear way to constrain app layout on home screen w/o completely replacing the Launcher. Is it worth hacking the Launcher source?
  6. Mesh on Android using OLSRd current requires root access. In order to run on unrooted Android devices, we need (a) proper power management for Ad Hoc mode wifi, (b) APIs to enable Ad Hoc mode, and (c) APIs to manipulate kernel routes.
  7. We're building libraries without thread support because Android's "Bionic" libc has an eccentric thread library. Linking with -lpthread fails because the thread functionality is bundled into -lc. Probably just providing an empty libpthread.so would help a lot.
  8. Some work has been done to build GNU libc for Android. This bloats activities even further, but might help ease library porting.
  9. Porting gobject-introspection will be painful because its makefiles are not set up for cross-compiling. Some steps want to run on the target hardware, which is difficult in the Android environment.

Bottom line

I can see how the whole Sugar stack can be put together on the Android platform. The hardest part is probably just setting up packaging and a good and repeatable build environment for the different components, and getting enough adoption of this that patches to support Android can be pushed upstream. Many of the important pieces can be developed in parallel (Theme, Journal, Mesh, Friends, Home, library porting, etc). A little early to tell how hard it will be to port existing Sugar activities to the new Python/pygobject/GTK3 framework.

Syndicated 2011-04-12 17:40:48 (Updated 2011-04-12 19:08:31) from C. Scott Ananian

4 Apr 2011 (updated 5 Apr 2011 at 17:08 UTC) »

Exploring New Technologies

Last Monday I rejoined One Laptop Per Child as Director, New Technologies. My mandate is hardware and software for the XO-3, OLPC's upcoming ARM-based tablet computer for education in the developing world. The new machine should be lower cost, lower power, more indestructible, more powerful, and potentially more expandable than ever. There are about two million machines in the XO-1 family (XO-1, XO-1.5) in the hands of kids today. The XO-3 will build upon this impressive foundation to reach further into the poorest and least-connected regions of the world.

I will kick-off my work with a series of four week-long sprints between now and eduJAM Uruguay to investigate a number of possible directions for the educational software stack on the XO-3 tablet. On the XO-1—series machines OLPC ships Sugar, an impressive collection of educational software developed by Sugar Labs. How can we best keep the best of Sugar while yanking the UI forward into a touch-friendly tablet world?

  1. This week (April 4-8) I'll begin by working on a port of the GTK3 UI library to Android. The GTK3 library contains touch support missing from the GTK2 library on which Sugar is currently based. The end goal here would be a full port of the Python/GTK-based Sugar APIs, running on something like the Honeycomb Android OS. Our existing educational activities could be ported to the new APIs without too much difficulty, but we'd largely use the existing Android OS facilities instead of the parts of Sugar concerned with low-level system management. To clarify: this is a preliminary exploration—we haven't decided to base the tablet software on Android (or anything else) yet.
  2. The next week brings a new direction. During the week of April 11-15 I will start porting Python/GTK3 to Chrome or ChromeOS via the Google NativeClient plugin. This path would result in activities which more fully integrate with web technologies—even in disconnected regions of the world. On desktop machines, Sugar activities could be run inside the Chrome browser, while ChromeOS (or another embedded OS running chrome/webkit) would provide the system management functions on tablet machines like the XO-3. As with the Android port, this is an exploration, not a definite software direction.
  3. The week of April 18-22 I hope to focus on mesh networking. This has a somewhat checkered history in our deployments; I hope to identify the remaining roadblocks and map a way forward to make this a flagship feature of the XO-3 software.
  4. The week of April 25-29 is for the existing Python-based Sugar codebase. In order to continue moving forward, it needs to migrate to GTK3, gobject-introspection, and some other key enabling technologies. I believe it would also benefit from language-independent APIs and better modularization to allow a more incremental migration path.

The following week is Conozco Uruguay and the Uruguay EduJAM where I'll present my progress on these initial exploratory projects and discuss the path ahead with the wider OLPC and Sugar communities. Clearly, a week each is not enough time to finish any of these projects! But the focused effort should help to better identify the promise, roadblocks, and challenges in each of these paths, which then in turn will help us to plan the future.

Syndicated 2011-04-04 21:48:52 (Updated 2011-04-05 04:47:48) from C. Scott Ananian

21 Feb 2011 (updated 4 Apr 2011 at 22:10 UTC) »

Taste, user experience, and engineering

A recent article on Nokia's internal culture contained this interesting quote:

Designers are also, by training and predilection, inclined to design for the usual, where engineers are taught a kind of rigor that compels them to account for, and overweight, low-probability events.

This does seem to me to often be a fundamental problem in not only interaction and UI design, but also internal programming APIs and interfaces. Good engineering is a clever balance; as Larry Wall has said: "Easy things should be easy, and hard things should be possible." An engineering mindset often fixates on the hard things (the "interesting part of the problem"!) and tries to make the hard things easy (or easier), at the risk of making the easy things hard. The end result is failure.

Truly elegant engineering involves finding a view of the problem where the hard parts of the problem disappear. We're not always fortunate enough to find that solution. In falling back to a practical/possible solution, we must be careful to ensure that we keep the easy things easy — it's fine if the hard things are difficult, so long as they are possible. Effort spent making the hard things easier is wasted if it makes the easy things harder. The goal is not a uniform mediocrity of design.

Syndicated 2011-02-21 03:48:25 (Updated 2011-04-04 21:19:45) from C. Scott Ananian

Improving Hunt Software/Improving Google Docs

There's been a lot of discussion about publishing and sharing the software that Mystery Hunt teams use to collaborate to solve puzzles. This is mostly misguided, IMO: teams are very different, and they organically grow solutions to fit their unique processes. On the other hand, an increasing number of teams (including my team, Codex), are building their collaboration software on top of Google services, especially Google Docs and Spreadsheets. Rather than trying to collaborate on One True Hunt Team Software, I think it would be far more useful (for all teams) to lobby for improvements to Google's services. These raise the bar for everyone, and indirectly benefit many other people with collaborative processes.

So here's my list of improvements I'd like to see in Google services:

  1. Integrating Docs and Spreadsheet. If we had an initial "sheet" of the spreadsheet with editable formatted text (not spreadsheet cells) we could actually do away with the wiki we use for capturing free form thoughts and links related to a puzzle.
  2. Integrating Spreadsheet chat, Google Talk, and Jabber. We could just use the chat in the spreadsheet if it were open and accessible, instead of creating our own per-puzzle chat rooms.
  3. Making publish and "setAnonymous" access available via APIs that actually work. We need to use Google Doc Script to do the setAnonymousAccess call, which is not exported via the otherwise-more-complete GData APIs, and drive a headless Firefox 2 instance via Selenium to get the publish bits enabled for the spreadsheet. That's ridiculous.
  4. Providing a way for Google Doc Scripts on a spreadsheet to export data more easily. We can use a Google Form to create a spreadsheet for a puzzle, but no easy way to provide a link to that spreadsheet on the page that results after form submission, or redirect from there.
  5. IIRC Google Talk support for multi-user chat is still barely supported. It doesn't use the standard Jabber protocols, for one. If this were a better supported/more standard service, we wouldn't have to run our own Jabber server.
  6. And, of course, the "next generation" of all this would integrate audio and video into the chat as well. Video is probably more useful, as it communicates human emotional cues. Audio isn't easily archived or searchable, and doesn't work well in crowded rooms, so it is less useful to us. But it would be great if we could actually see some/many/most of the particants in ringhunters, maybe little live video icons next to their faces.

Any further suggestions from other teams?

Syndicated 2011-01-18 06:53:12 from C. Scott Ananian

Codex wins!

We won the Mystery Hunt this year! You can read a Boston globe article which mentions us, but mostly talks about Palindrome.

That means we have to—er, "get to"—write the Mystery Hunt for 2012. My free time for the next year has just vanished.

Syndicated 2011-01-18 05:32:43 from C. Scott Ananian

75 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!