Search Results: "andy"

8 May 2009

Christoph Haas: Thanks for the great time, KDE

After years of being a dedicated KDE user it seems like it s finally time for me to go back to Gnome. I once tried KDE 4.x from the Debian experimental branch knowing that it s probably unstable and will require a lot of patience. But I was willing to report bugs and dive into new things. It didn t take long though to find out that graphics were extraordinarily slow with the new desktop effects . The worst was resizing a konsole (KDE terminal window). It took 25 seconds until the window was resized and redrawn! On the interweb I found KDE developers rant about NVidia who didn t support some special extension they needed. They suggested to get an ATI card instead. (No, thanks, I was struggling with the crappy radeon and fglrx drivers on my new work laptop and am sick of ATI for Xorg.) Or I could use a bare XTerm instead. Yeah, right. So I couldn t use the desktop effects. After all I used the non-free NVidia driver for years and it never let me down. I don t mind doing without eye candy. But the desktop effects were about the only serious way to switch between virtual desktops. Point the mouse into a corner or edge of the screen and get a zoom-out bird s view of the virtual desktops. Nice but quickly annoying. Besides you had to push the mouse pointer a few pixels into the edge (it s not sufficient to just hit the edge) which means that after 10 desktop switches I had to lift the mouse and set it back on the mousepad. Another annoying issue is that up to now I can t assign functionality to every key on my keyboard any more. I had a neat trick by having 3 3=9 virtual desktops and use my numpad keys 1 to 9 to page through them. 0 on the numpad opened a new shell window. + on the numpad maximized a window. But now I couldn t assign any of those numpad keys. I pressed the 1 but KDE didn t detect Numpad_1 but just 1 . Guess how useful it is to not be able to type the 1 any more. There is a low-priority bug report for KDE from users who want this fixed but it will likely not happen any time soon. So the only way to switch desktops was to poke on the tiny pager widget in my panel. Yuk. Not to mention that I couldn t put icons on the desktop any longer. There was just a sissy widget that I could use for that purpose but it didn t work like a conqueror or dolphin at all. It was pretty amusing when in KDE 4.2 there was suddenly a feature to re-enable the old behavior. Let me guess, KDE developers - I wasn t the only user you couldn t persuade of the new paradigm? Next evil thing was performance. KDE 4 takes ages to load. Simple window managers get me started within seconds. Even Gnome. But KDE takes 30 seconds until it s loaded plus some disk grinding in the background. And memory usage wasn t nice either. And what finally made me mad was stabilty - or rather lack thereof. Everytime the screen saver ran my kbluetooth module crashed. kmail crashed even more frequently than before. (I loved kmail for it s great customizability and feature set.) plasma (the actual window manager) died at least twice a day. Suddenly the panels were looking ugly or crashing. As a Debian developer I have to follow the unstable branch on my workstation. And there is no distinction between KDE 3 and KDE 4 any more so a dist-uprade inevitably gets all of my applications upgraded to KDE 4 (plus an hour of manual engineering in aptitude because half of my applications weren t upgraded automatically due to different application names and I had a mixed environment). So there I was with KDE 4.2. I really worked with it for a month. I tried hard to get acquainted to its bloatedness and instability. It s really a nice technological preview of what might be possible in the future. Everything is really automatic. Mounting external media. New ways to find programs (although I m not happy with the new K start menu). Funny effects and nice eye candy. But it s far from the rock solid desktop environment that I was used from KDE 3.5.8. So there I am on Gnome now. I was switching back and forth. One day working on KDE 4.2 and the other day using Gnome 2.26. And although it makes me feel sad I think it s finally time to say goodbye to KDE 4. I have invested a good amount of time and energy into it - even just from a user perspective. But it s not ready. And I finally need to get some work done. A number of projects suffered from my playfulness (my ispmail tutorial, screenshots.debian.net, debexpo, my kids) and it s time to get back to work. And Gnome was pretty surprising. With compiz I have the KDE desktop effects working (here they really do) and they are all customizable. I can assign keys properly again (even the numpad). Everything is pretty fast and stable. I have replaced kmail and its buggy shared calendar feature by Icedove (aka Thunderbird) with the Lightning plugin. Worked from the first minute and hasn t crashed in a week (just have to remember next time to install libstdc++5 to be able to use Lightning). With enigmail I finally have a proper simple working PGP key management that doesn t die and is buggy like hell like in kgpg. And there s the nice Nostalgy add-on that allows me to file emails into IMAP folder quickly again - a feature that just kmail seemed to support so far. Oh, and I see new mail instantly because Icedove supports the IDLE command while kmail has never learned that neat little trick. The Gnome file manager isn t really great for my taste but it s doing its job (dolphin is just much nicer). It s not as nice as KDE but I had to learn that working and stable weighs more than nice. The hard way. And many things I liked about KDE 4 (like starting a new program with Alt-F2 and having a smart application finder and simple calculator in one) are built into Gnome, too. So why bother. Thanks, KDE, for the years of fun and service. I ll surely miss you. Get back to me should you grow up one day.

4 May 2009

Biella Coleman: Markmail

This looks like a handy tool for wading through mailing lists. Has anyone used it with impressive/unimpressive results?

Manoj Srivastava: Manoj: Reflections on streetcars

Recently, I have made fairly major changes to kernel-package, and there were some reports that I had managed to mess up cross compilation. And, not having a cross-compilation tool chain handy, I had to depend on the kindness of strangers to address that issue. And, given that I am much less personable than Ms Vivien Leigh, this is not something I particularly look forward to repeating. At the onset, building a cross compiling tool chain seems a daunting task. This is not an activity one does frequently, and so one may be pardoned for being non-plussed by this. However, I have done this before, the most recent effort being creating one to compile rockbox binaries, so I had some idea where to start. Of course, since it is usually years between attempts to create cross-compiling tool chains, I generally forget how it is all done, and have to go hunting for details. Thank god for google. Well, I am not the only one in the same pickle, apparently, for there are gobs of articles and HOWTOs out there, including some pretty comprehensive (and intimidating) general tool sets to designed to create cross compilers in the most generic fashion possible. Using them was not really an option, since I would forget how to drive them in a few months, and have a miniature version of the current problem again. Also, you know, I don t feel comfortable using scripts that are too complex for me to understand I mean, without understanding, how can there be trust? Also, this time around, I could not decide whether to cross compile for arm-elf, as I did the last time, or for the newfangled armel target. A need for quickly changing the target for the cross compiler build mechanism would be nice. Manually building the tool chain makes a wrong decision here expensive, and I hate that. I am also getting fed up with having to root around on the internet every time I wanted to build a cross compiler. I came across a script by Uwe Hermann, which started me down the path of creating a script, with a help option, to store the instructions, without trying to be too general and thus getting overly complex. However, Uwe s script hard coded too many things like version numbers and upstream source locations, and I know I would rapidly find updating the script irritating. Using Debian source packages would fix both of these issues. I also wanted to use Debian sources as far as I could, to ensure that my cross compiler was as compatible as I could make it, though I did want to use newlib (I don t know why, except that I can, and the docs sound cool). And of course the script should have a help option and do proper command line parsing, so that editing the script would be unnecessary. Anyway, all this effort culminated in the following script: build cross toolchain, surprisingly compact. So I am now all set to try and cross compile a kernel the next time a kernel-package bug comes around. I thought that I would share this with the lazy web, while I was at it. Enjoy. The next thing, of course, is to get my script to create a qemu base image every week so I can move from user mode Linux to the much more nifty kvm, which is what all the cool kids use. And then I can even create an arm virtual machine to test my kernels with, something that user mode linux can t easily do.

1 May 2009

Simon McVittie: Implementing D-Bus clients with telepathy-glib (and telepathy-qt4)

(The much-delayed part 2 in an ongoing series: shiny things in telepathy-glib) Over a year ago I explained my first major round of work on telepathy-glib, with which it could be used to implement D-Bus services. I started to write this post shortly after, but then got distracted by a bee or something; recent discussion about having a D-Bus binding in GLib has finally prompted me to finish it. The second major round of work on telepathy-glib dealt with implementing client code, and went sufficiently well that telepathy-qt4 (currently under development) uses essentially the same model. Again, while telepathy-glib is intended for Telepathy implementors, I think TpProxy's ideas are generically useful, particularly for "large" D-Bus APIs.

Some background: dbus-glib and libtelepathy
GObject-CRITICAL: Assertion failed: proxy->convenient
The life-cycle of a DBusGProxy (PD clipart credit: karderio and Andy)
The API provided by dbus-glib for client code is, er, rather less than ideal. The basic object is DBusGProxy, which has a few problems. There's one per interface, rather than one per object; this leads to a maze of twisty GObjects, all suspiciously similar. Our old client library, libtelepathy, got round this by subclassing DBusGProxy to make helper objects called TpChan, TpConn etc., which were simultaneously the proxy for the "main" interface (Channel, Connection etc.), and a factory for proxies for the other interfaces (like Channel.Type.Text and Channel.Interface.Password). This still wasn't ideal, but it was a start. If you use a DBusGProxy in any way after it has emitted the destroy signal, this is considered to be invalid use of the API, and dbus-glib asserts all over the place. We'd rather it didn't do that - remote objects becoming invalid is a fact of life, and if you don't immediately discard all your references to those objects, remote operations on them should just give you a runtime error. You have to be prepared to handle such runtime errors already, because any IPC call can fail at any time. The main API for calling methods uses varargs and is rather subtle. Notably, the calling convention for variant parameters (of D-Bus signature 'v') is not consistent with the calling convention for any other container. For any other container, for instance a GPtrArray *, you pass in a GPtrArray ** pointing to a GPtrArray * variable containing NULL; on success, a pointer to a new GPtrArray is written into that variable. For variant parameters, though, you must pass in a GValue * pointing to a zero-filled GValue, and the result will be written into that GValue. dbus-binding-tool generates thin wrappers around this method-calling API which provide type-safety, although they can't directly specify a non-default timeout. As for signals, before binding to a signal, you have to tell dbus-glib about its signature. This tells dbus-glib how it should push the signal arguments onto the C stack (in GObject terminology: how it should marshal them), to match the signature of the signal-handler function. The documentation claims that this isn't necessary for objects supporting the Introspect method, but that's untrue - on the other hand, if the documented behaviour actually happened, I would consider this to be a critical bug in dbus-glib, since it would enable remote objects to crash dbus-glib clients (by causing signal arguments to be pushed onto the stack in a way that does not match the signature of the signal handler). Of course, the signal-adding function takes varargs, and has to be called exactly once per signal per object. If you don't, dbus-glib asserts when you connect to the signal; if you call it twice, dbus-glib asserts anyway.

TpProxy TpProxy is a GObject subclass vaguely inspired by Python's dbus.proxy.ProxyObject. It isn't a subclass of DBusGProxy, which lets us encapsulate dbus-glib almost completely - in fact, all the references to DBusGProxy are in a separate header, proxy-subclass.h, only used by subclasses of TpProxy (as opposed to normal library API users). TpProxy instances are per-remote-object (per-object-path) like in dbus-python, rather than per-interface like in dbus-glib or QtDBus. As explained below, I believe that this is the most natural object mapping for D-Bus interfaces; in practice it tends to lead to clearer code for us, since one remote object often maps nicely to one UI element (of course, if your objects only have one interface, this approach is no better or worse than dbus-glib's). TpProxy provides support for the following common D-Bus things:
  • Calling methods
  • Connecting to signals
  • Objects becoming invalid
  • Objects with optional interfaces
  • Extensibility
It doesn't currently provide any particular help with Properties - the Properties interface is just another interface as far as we're concerned. We find that, in practice, that's not a problem (even though we use D-Bus properties extensively). In telepathy-qt4 we basically reinvented TpProxy in C++, as Tp::DBusProxy. I've put in some comments below illustrating how the general ideas we used in TpProxy translate into a different object mapping.

Calling methods Method calls on TpProxy are done through auto-generated wrapper functions, much like DBusGProxy. These look something like this:
typedef void (*tp_cli_channel_callback_for_close) (TpChannel *proxy,
    /* any 'out' arguments would go here - Close() doesn't have any */
    const GError *error, gpointer user_data,
    GObject *weak_object);
TpProxyPendingCall *tp_cli_channel_call_close (TpChannel *proxy,
    gint timeout_ms,
    /* any 'in' arguments would go here - Close() doesn't have any */
    tp_cli_channel_callback_for_close callback,
    gpointer user_data,
    GDestroyNotify destroy,
    GObject *weak_object);
Methods for some interfaces, like DBus.Properties, are available on TpProxy itself; others, like Telepathy's Channel.anything, are only available on a particular subclass, like TpChannel. Things to note here:
  • It's an asynchronous call with a callback. General design principle: "this is IPC, get over it". We don't try to hide the fact that IPC is taking place by doing pseudo-blocking calls.
  • The timeout is explicit (although you can always pass -1 to let libdbus pick a "reasonable" default for you). This is because the remote service might not respond, and API users should be at least vaguely aware of this: "this is IPC, get over it".
  • The callback isn't a GCallback; it has an explicit signature, for some semblance of type-safety (it's not much, but it's better than nothing).
  • The callback takes a GError, because any IPC call can fail for any reason.
  • A TpProxyPendingCall * is returned. This is a pointer to an object that only exists until just after the callback is called (so you can ignore it if you don't want it), with a method you can call to cancel the method call (with hindsight this is not ideal, and if I was writing this API now, I'd use gio's GCancellable). "Cancel" is perhaps slightly misleading: the method call still takes place (it was already in libdbus's outgoing queue) but the result gets ignored and the callback isn't called. This is mostly so you an object can forget all the calls it was busy making at the time that the results become irrelevant (e.g. the object is destroyed).
  • There is an extra weak_object argument, which is weakly referenced and is passed to the callback: in practice, most users of telepathy-glib use this as well as or instead of user_data. If the weak_object runs out of references, the callback is automatically cancelled, which means that in practice, explicit cancellation is almost never needed.
  • The generated code has as its first argument a suitable subclass of TpProxy, in this case TpChannel (we tell the code generator about subclasses).
  • You can't see it in the API, but the TpProxy gains an extra ref while a method call is in progress, so you never have to worry about what happens if the proxy gets unreffed during a method call.
  • There's an explicit destructor for the user_data, which is called even if you "cancel" the method call.
In telepathy-qt4, these methods are on small generated helper classes similar to dbus-python's dbus.Interface, one per interface (we provide accessors for them on the non-generated DBusProxy subclass). Instead of using callbacks, we return a temporary QObject per call, which emits a Qt signal on success or failure (that's how all async calls in QtDBus work).

Connecting to signals Similarly, signals have some generated functions:
typedef void (*tp_cli_channel_signal_callback_closed) (TpChannel *proxy,
    /* any arguments would go here - Closed doesn't have any */
    gpointer user_data, GObject *weak_object);
TpProxySignalConnection *tp_cli_channel_connect_to_closed (TpChannel *proxy,
    tp_cli_channel_signal_callback_closed callback,
    gpointer user_data,
    GDestroyNotify destroy,
    GObject *weak_object,
    GError **error);
API notes for these:
  • The callback doesn't take a GError any more, because signals can't fail; the weak_object and the user_data are the same as for method calls
  • This isn't actually a GObject signal at all: those aren't particularly typesafe, and lack namespacing. This might not be very binding-friendly, we haven't tried doing that yet... it might be worth introducing a signal with details, like in dbus-glib, for which these functions are "C bindings".
  • The returned TpProxySignalConnection lets you disconnect from the signal, just like the TpProxyPendingCall above; it can safely be ignored
  • Similarly, if the weak_object dies, then the signal automatically disconnects
  • It is possible for connecting to a signal to fail: this happens if the proxy doesn't actually have the requested interface. If this happens, it's graceful, not a crash. In practice, the flow of code is almost always such that error can safely be NULL because the interfaces are already known.
In telepathy-qt4 the per-interface generated helper classes emit Qt signals. In many cases, we end up proxying these signals by responding to them in the hand-written Tp::DBusProxy subclass by emitting a different signal, in order to give them a nicer representation.

Becoming invalid This is IPC, and any error can happen to you at any time. We found that it was useful to have a general concept of "this object is no longer useful", so we introduced the concept of an object becoming invalidated. The invalidation reason is stored on the object as a GError. If this GError is NULL (as it is initially), then the object is still expected to be valid; if it's non-NULL, the remote object has vanished and the local proxy no longer works. There are several ways a TpProxy can become invalid:
  • its bus name falls off the bus (the process exited or crashed)
  • application-specific reasons (usually triggered by a D-Bus signal in a subclass, like the Telepathy Channel's Closed signal)
  • the GObject gets disposed
Method calls on an invalidated object always fail, with the invalidation reason as the error. This means that calling a method on a TpProxy should never crash your process. The method's callback has to be prepared to handle an error in any case, because this is Sparta^WIPC, so there's no loss in giving it another error. Connecting to signals on an invalidated object always fails, and any existing signal connections are disconnected when it becomes invalidated. This means that if a new remote object appears, and it happens to have the same object path, bus name etc. as the old one, you won't get its signals. A TpProxy can either be bound to a unique bus name or a well-known bus name. In the equivalent code in telepathy-qt4, we call this "stateful" or "stateless" - these names don't capture the intention perfectly, but they're the best we could come up with. A proxy for a stateful API like Telepathy's Channel should always bind to a unique name - when the unique name falls off the bus, the TpProxy becomes invalidated automatically, representing the fact that the Channel you had no longer exists, and nothing can be a perfect replacement for it (the VoIP call has already been terminated, you've already left the chatroom, or whatever - if you make another Channel, that's e.g. a distinct VoIP call). A proxy for a stateless API like Telepathy's ConnectionManager, where an exiting process can disappear, be service-activated again, and still have exactly the same API, should bind to the well-known name. Proxies for well-known names aren't invalidated when the process exits. Qt doesn't have a natural equivalent for GError, so the invalidation reasons in telepathy-qt4 are just a pair of strings, the namespaced name and the message - basically a libdbus DBusError. The principle is the same, though.

Optional interfaces As mentioned above, TpProxy instances are per-remote-object (per-object-path) like in dbus-python, rather than per-interface like in dbus-glib or QtDBus. I believe that this is the most natural object mapping for the D-Bus object model, because the D-Bus interfaces on a remote object can behave like any of these:
  • classes and subclasses (Telepathy.Channel.Type.Text is a Telepathy.Channel)
  • shared interfaces (some Telepathy.Channel objects, of many Types, implement Telepathy.Channel.Interface.Group; any D-Bus object can implement DBus.Properties)
  • optional features (some Telepathy.Channel.Type.Text objects implement Telepathy.Channel.Interface.ChatStates, some do not)
  • discoverable extensions (some Telepathy.Channel.Type.Text objects implement Telepathy.Channel.Interface.Messages, which is more or less Text 2.0)
The way in which interfaces are discovered is also variable. The "classic" D-Bus way to discover interfaces would be to call Introspect. Telepathy services still support that style of introspection, but we don't use it for anything beyond d-feet:
  • Introspect returns a blob of XML, which you have to parse into something useful; if it was in a D-Bus data structure, you'd already have some sensible data structure.
  • Finding out more information about the supported interfaces than their names isn't very useful: in a static language like C you already need to know the methods, signals, properties and their signatures in order to write and compile your code, and in a dynamic language like Python consumers of Introspect end up being remotely crashable by services with unexpected method signatures (this is one of dbus-python's big mistakes in my opinion).
  • If a method that you want to call turns out to be missing, the worst that can happen (in a competently written service) is that it fails with a D-Bus error - and you have to handle D-Bus errors anyway, because this is IPC and anything could fail.
  • Static bindings like dbus-glib have poor support for removing interfaces for which C code exists at runtime, whereas Telepathy needs features like an IM connection that might or might not support avatars (we don't get to find out until we've successfully connected to the server).
Instead, our older interfaces have a method on the "base class" (Channel, Connection etc.) called GetInterfaces, which just returns an array of strings. Newer interfaces (like Account), and older interfaces that have been ported (like Channel), have a property called Interfaces which is, again, an array of strings - this lets us combine the download of the interfaces list with downloading other basic information in a GetAll call. To cater for all these ways to use interfaces, the TpProxy base class has very basic support for interface discovery - you can ask it whether it supports an interface, and you can tell it that it does, in fact, support an interface. Asking which interfaces are supported is directly useful for library users; it's also used as a check by the generated method-call and signal-connection stubs, which return a canned error (Telepathy.Error.NotImplemented in Telepathy's case) if the object isn't known to have the interface. Telling TpProxy that it does support an interface is intended for use by subclasses, and might have been protected if we were writing C++: what happens in practice is that a concrete subclass like TpChannel knows how to discover the fully supported interfaces for this particular object, does so, and calls methods on the TpProxy to tell it which interfaces can work.

Extensibility The API stubs used by TpProxy to call methods and bind to signals are generated from XML documents containing an augmented form of D-Bus introspection data. These XML documents contain various Telepathy-specific extensions, but none of the extensions are language-specific - telepathy-glib, telepathy-python and telepathy-qt4 all operate from exactly the same XML specification. telepathy-qt4's different object-mapping did require us to tighten up some rules that were previously only conventions, but even so, the format is the same. I think this is vitally important - it just doesn't scale to have one set of language-specific annotations in a D-Bus API for each language that will have bindings. One thing that we make heavy use of is what I call "Ugly_Case", which is camel-case with underscores at word boundaries. This gives us a simple, unambiguous and foolproof rule to use in code generators whenever we generate any of the popular conventions for identifiers:
  • CamelCase: delete underscores
  • javaCamelCase: force everything before the first underscore to lower case, then delete underscores
  • lower_case: force everything to lower case, retain underscores
  • UPPER_CASE: force everything to upper case, retain underscores
dbus-glib, by contrast, applies a complex and subtly buggy algorithm to the CamelCase D-Bus names, which results in our SendDTMF method being mapped into GLib as send_dt_mf, and requires that telepathy-glib's Python reimplementation of dbus-binding-tool uses a bug-for-bug compatible implementation (we ended up reimplementing dbus-binding-tool in order to generate the TpProxy-based bindings). Our code generation tools are still rather ad-hoc, because so is our spec format, but for draft interfaces it's possible to copy them into individual projects and use them to generate additional methods for TpProxy or any subclass. This is how we implement unfinished APIs like geolocation in Empathy, for instance. The Interfaces or GetInterfaces hook described above is entirely usable for these extension interfaces, and in fact that's how they're set up. In telepathy-qt4, the generated method stubs are genuine C++ methods, so we can't just append methods to an existing class: this is why we have one helper class per interface, so individual clients can generate a helper class for their particular version of an unfinished API, and instantiate an object of this class attached to a particular Tp::DBusProxy. When an interface becomes stable, it can be added to the set of interfaces for which code is generated in telepathy-glib or telepathy-qt4, at which point any client or service that was already using the final draft of that interface can easily be ported to the library version using sed (the API remains the same).

Becoming ready The concept of being "ready" does not directly exist in TpProxy, but is implemented in TpChannel, TpConnection and TpConnectionManager. The idea is that a freshly created proxy object isn't really fully usable yet - you have to connect to basic signals and recover the initial state of the remote object, as well as checking which extension interfaces are supported. In many well-designed D-Bus APIs you can do this initial setup with a few signal connections and a DBus.Properties.GetAll call. After doing that initial setup (which has to be done asynchronously, because it's IPC), the TpProxy subclass has a local cache of the remote object's state (not necessarily in the same format as the representation on the bus), which can be accessed synchronously at any time, and will be updated in response to change-notification signals. TpChannel and subclasses like it have explicit support for checking for readiness, and having a callback called when the object is ready or invalidated (whichever happens first). The "ready" property also supports the GObject notify signal. telepathy-qt4 took this concept and ran with it - there is library support for objects that can become ready, including a mixin. If I had as much time to work on telepathy-glib as I wish I had, this would be one of the first telepathy-qt4 features to be added to telepathy-glib.

Features becoming ready Going beyond that, in an extensible framework like Telepathy it's probable that not every client understands (or wants to understand) every feature of every object, so it's highly inefficient for every proxy object to subscribe to all the change notification signals and cache all the remote state on the off-chance that the library user wants them. In the API for TpContact (which is not actually a TpProxy for various reasons) we introduced the concept of optional features; telepathy-qt4 extended this idea throughout the library. The idea is that each library user knows which of the optional features are "interesting" to it, and makes a single asynchronous call (which expands into a series of D-Bus calls inside the library) to download the state for core functionality plus all of the selected features, and subscribe to change notification for all of those. This is another telepathy-qt4 thing that telepathy-glib still needs to catch up with; until someone works out how to make the clone() syscall apply to programmers, I fear all libraries are doomed to lag behind how their designers want them to look :-) (license: CC-BY-3.0 / LGPL-2.1+)

26 April 2009

Florian Ragwitz: Declaring Catalyst Actions

For a long time the Catalyst Framework has been using code attributes to allow users to declare actions that certain URLs get dispatched to. That looks something like this:
sub base    : Chained('/')    PathPart('') CaptureArgs(0)   ...  
sub index   : Chained('base') PathPart('') Args(0)          ...  
sub default : Chained('base') PathPart('') Args             ...  
It's a nice and clean syntax that keeps all important information right next to the method it belongs to. However, attributes in perl have a couple of limitations. For one, the interface the perl core provides to use them is horrible and doesn't provide nearly enough information to do a lot of things, but most importantly attributes are just plain strings. That means you will need to parse something like "Chained('base')" into (Chained => 'base') yourself to make proper use of them. While that's easy for the above example, it can be very hard in the general case because only perl can parse Perl. It's one of the reasons you can't use Catalyst::Controller::ActionRole to apply parameterized roles to your action instances, because parsing parameters out of things like Does(SomeRole => names => [qw/affe tiger/], answer_re => qr/42/ ) would be awful and wrong. With Catalyst 5.8 most of the attribute related code has been removed from the internals. It's now using MooseX::MethodAttributes to do all the heavy lifting. Also the internals of how actions are registered have been refactored to make it easier to implement alternate ways without changing the Catalyst core. As a proof of concept for this I implemented a new way of declaring actions that's very similar to how Moose provides it's sugar functions. You can get it from github. With that, the above example looks like this:
action base    => (Chained => '/',    PathPart => '', CaptureArgs => 0) => sub   ...  ;
action index   => (Chained => 'base', PathPart => '', Args    => 0    ) => sub   ...  ;
action default => (Chained => 'base', PathPart => '', Args    => undef) => sub   ...  ;
It also moves method declaration from compiletime to runtime, making this possible:
for my $action (qw/foo bar baz/)  
    action $action => (Chained => 'somewhere', Args => 0) => sub  
        my ($self, $ctx) = @_;
        $ctx->stash->  $action   = $ctx->model('Foo')->get_stuff($action);
     ;
 
Admittedly, that's all very ugly, but illustrates well what kind of things we're able to do now. But it doesn't need to be ugly. With Devel::Declare we have a great tool to add our own awesome syntax to perl, similar to how things like MooseX::Method::Signatures, MooseX::MultiMethods and MooseX::Declare do. So how would a declarative syntax for Catalyst controllers look like? I don't know. Ideas include something like this:
under /some/where, action foo ('foo', $id)   ...  
to mean:
sub foo : Chained('/some/where') PathPart('foo') CaptureArgs(1)   ...  
Adding Moose type constraints to this would be interesting, too, and make validation of captures and arguments a lot easier. Multi dispatch similar to MooseX::MultiMethods could be handy as well:
under /some/where  
    action ('foo', Int $id)  
        # find and stash an item by id
     
    action ('foo', Str $name)  
        # search items using $name
     
    action ('foo', Any $thing)  
        # display error page
     
 
So you see there are a lot of possibilities that should be explored. Unfortunately I have no idea what kind of syntax and features people would like to have, so your feedback on this would be much appreciated. :-)

22 April 2009

Matthew Palmer: Really, Really Distributed Revision Control

While I'm not a fan of cut-n-paste coding, on the odd occasion it's handy to grab a snippet of code out of someone else's blog and plop it in. Jeff Atwood of Coding Horror has a solution to some of the downsides of ripping a bit of code from somewhere on the Internet: publishers of code snippets generate a new GUID, tag each code snippet with a GUID, and you paste that comment in with the rest of the code when you take it. Then, if you (or someone else) needs to look at the context of the chunk of code, find it's author, look for improvements or commentary, or see who else has used that snippet in their own projects, you can search for that GUID and you should come up with only that GUID as a result.
What I propose is this:
// codesnippet:1c125546-b87c-49ff-8130-a24a3deda659
- (void)fadeOutWindow:(NSWindow*)window 
        // code
 
Attach a one line comment convention with a new GUID to any code snippet you publish on the web. This ties the snippet of code to its author and any subsequent clones. A trivial search for the code snippet GUID would identify every other copy of the snippet on the web:
http://www.google.com/search?q=1c125546-b87c-49ff-8130-a24a3deda659
How very, very cunning. He also proposes that if you modify a snippet and republish it, you should keep the old GUID and also add one of your own, so you can track the origin and help other people find your alternate version. Attaching unique identifiers to chunks of code and sending them all around the Internet. Does this sound like distributed revision control to anyone else? A lot easier to master than Git's UI, too...

19 April 2009

Kees Cook: recording from PulseAudio

Every PulseAudio "Sink" has a "Source" named "monitor". This lets you attach to a given Sink and chain more stuff to it, for example, recording the audio that is playing through PulseAudio at any given moment. This is very handy for creating, for example, PubQuiz-style clips of songs, movies, etc. Here is a script to find the monitor for the most recently added Sink, record from it, and shove it through "sox" to get a WAV instead of raw sound data (requires recent sox, Pulse, etc):
#!/bin/bash
WAV="$1"
if [ -z "$WAV" ]; then
    echo "Usage: $0 OUTPUT.WAV" >&2
    exit 1
fi
rm -f "$WAV"
# Get sink monitor:
MONITOR=$(pactl list   grep -A1 '^\*\*\* Source #'   \
    grep '^Name: .*\.monitor$'   cut -d" " -f2   tail -n1)
# Record it raw, and convert to a wav
echo "Recording to $WAV ..."
echo "Close this window to stop"
parec -d "$MONITOR"   sox -t raw -r 44k -sLb 16 -c 2 - "$WAV"

17 April 2009

David Welton: Hecl - for Quilting!

Looking through the logs for HeclBuilder.com, I found this site: http://www.patchwork-quilt-forum.de/dreieck-aus-quadrat-t2457-s20.html Which, according to the translation is a discussion on a German site dedicated to patchwork quilting about calculating the right lengths to cut triangles of cloth. I thought it was really cool to see - not because I'm interested in quilting, or the program is anything brilliant (it's simple and functional), but because enabling stuff like this is part of what I built Hecl for: to make mobile phone applications easier, quicker, and simpler to create. Someone went and typed in the code on Heclbuilder, got the program running, and now a number of people have a handy tool to do some calculations for their hobby, which is a heck of a lot easier than fooling around with SDK's, Eclipse or Netbeans, and so on and so forth. I hope to see more of that sort of thing in the future.

9 April 2009

Biella Coleman: From Open Source Software to Open Culture: Three Misunderstandings

A few weeks ago, I jotted down some thoughts about (false) expectations made on FLOSS/F/OSS, something that I wish I had more time to write about (teaching and other things seem to take most of my time these days). But before this year turned into the next one, I wanted to pass on a few additional (and similar though they enter into different territory) thoughts by O Reilly editor, Andy Oram: From Open Source Software to Open Culture: Three Misunderstandings

Biella Coleman: From Open Source Software to Open Culture: Three Misunderstandings

A few weeks ago, I jotted down some thoughts about (false) expectations made on FLOSS/F/OSS, something that I wish I had more time to write about (teaching and other things seem to take most of my time these days). But before this year turned into the next one, I wanted to pass on a few additional (and similar though they enter into different territory) thoughts by O Reilly editor, Andy Oram: From Open Source Software to Open Culture: Three Misunderstandings

31 March 2009

Sven Mueller: Link collection 2009/03

Well, I normally despise of thinks like this link collection, but I thought I might add it anyway, since these are useful links for me and if I don t post them here, I m likely to forget where to find them in the near future:
  1. Sean Finney has a nice post about storing the list of parameters a (shell) script got in a way that it can be restored later. Quite handy if your script walks through the arguments parsing them (and consuming them while doing so) but you want to be able to display them in a helpful way if the parsing fails at some point.
  2. A while ago, Ingo J rgensmann had a post that helps retrieving files from lost+found after a filesystem check, provided that you run his helper script on a regular basis. The same approach can also be used if you have a backup of all files, but lost the sorting work you did after the backup was done. This is possible because running the script can be done more often then you would normally do backups.
  3. He also has a small post about mtr oddities when IPv6 comes into play
  4. Adeodato Sim wrote about databases and when timestamps that store the timezone information really are more useful then timestamps that don t.
  5. Adeodato also has a short post on using ssh as a socks proxy, which can be quite handy if you are behind a firewall.
Update: Fixed link to Ingo s file retrieval from lost+found article. Thanks to Patrick Schoenfeld who pointed me at the wrong link.
Also thanks to the anonymous poster who found an alternative way to store and (in a way) restore commandline parameters. The solution doesn t work in an as general way as that by Sean Finney et al., but it is much shorter and therefore interesting for where it can be used (when you control how commandline parameters are processed). See comments on this post for details.

30 March 2009

Biella Coleman: Pure Data: FM Sprint in NYC and Berlin

FLOSS Manuals is proud to announce a three day book sprint for the Pure
Data FLOSS Manual. This sprint will take place simultaneously in New
York City and Berlin from Saturday 4 April to Monday 6 April. The Pure Data FLOSS Manual: http://en.flossmanuals.net/puredata There are possibilities to participate in person by coming to one of the
locations below, or remotely via the IRC interface built into the FLOSS
Manuals editing interface. Video conferencing may take place between the
venues as well. To participate, create a login at the PD FLOSS Manuals page: http://en.flossmanuals.net/bin/login/TWiki/WebHome?origurl=/bin/view/PureData/Introduction&skin=floss2 Discussion may also take place in the Pure Data mailing list: http://lists.puredata.info/listinfo/pd-list If you are in New York or Berlin, please join us at these locations! NEW YORK CITY * Contact: Hans-Christoph Steiner: hans@eds.org 718 360 4872 * Location (bring ID, you ll need to sign in): ITP/NYU Conference Room
721 Broadway, 4th Floor
NY, NY, USA
email me or call in case you can get past security: 718 360 4872 * Schedule:
Saturday: noon-midnight
Sunday: 10am-midnight
Monday: 9am-5:30pm (if we go later, we ll be in a different room) BERLIN * Contacts Derek Holzer: derek@umatic.nl +49 176 2812 5845
Adam Hyde: adam@flossmanuals.net +49 15 2230 54563 NK
ElsenStr. 52 (2.Hof)
Berlin, Germany
+49 176 20626386
http://www.myspace.com/enka52 * Schedule:
Saturday: noon-late
Sunday: noon-late
Monday: noon-late
SOME BASIC GUIDELINES: * This manual should address the widest possible user-base. Therefore,
objects which are cross-platform and in Pd Extended should have priority
over other solutions.
* Tone should be neutral and informative. Remember that humor doesn t
always translate well! ;-)
* Our readers are assumed to have little to no background in either
computer programming or digital signal processing, which much of the
existing documentation takes for granted. That s why this manual is
necessary! Please keep this in mind when explaining things.
* Please use existing the Audio Tutorials, Installing and Getting
Started chapters as a style guide.
* Keep the chapters small and self-contained. Ideally, chapters from
this manual could even be remixed into other FLOSS Manuals.
* Explain any jargon or technical terminology in-line the first time you
use it, and direct the reader to appropriate other chapters/manuals when
necessary.
* Please enter any new technical terms in the Glossary (we need to agree
on global format for glossary terms!).
* Screenshots:
Resolution? (Adam and I will work on this on Monday)
Please upload any complex patches, and make sure to label screenshot
with appropriate filename (see Audio Tutorials for examples)
Please keep explanatory text in the manual rather than only in the
screenshot, so that it can be text-searched by readers.
Please use anti-aliased fonts!
* All the chapters are moderated by Derek Holzer & Adam Hyde. Your
contributions will only be visible in the editing section until they
meet these guidelines, and after that they can be published to the main
page. Please let us know when your chapter(s) are ready for publishing
and we ll look them over. EXISTING CHAPTERS WHICH NEED HELP: # DataflowTutorials this section needs a lot of help in terms of style and content!!!!!
Tone is very informal, which doesn t help convey the information.
give titles to screenshots so that readers can tell which patches
match which images (some do this, some don t )
Math : examples/discussion of [expr]???
Order of connecting and [trigger] : explain the patches in-line,
rather than only in comments in screenshots (so that text is searchable,
copy/pasteable..)
Luka s screencaps are very aliased, to the point where you can t read
the ~ in the object names. Should they be redone at new resolution or
with antialiasing?
Possible janitors: Derek Holzer, Adam Hyde # PureGlossary format of object names = [italics in square brackets], must be
formatted correctly
format of glossary words in general text: we don t have one yet. Bold
on first use in chapter maybe? Needs formatting all through text. # ListofObjects incomplete, please add more libs
maybe more discussion of externals needed as well
formatting of object names? # PureLinks always welcome MORE CHAPTERS/SECTIONS TO DO (+ suggestions?): * GEM (in order of importance)(Derek can provide example patches for
much of this)
Basic VJ mixer (2 x
[gemhead]-[pix_film]-[alpha]-[colorRGB]-[pix_texture]-[rectangle] with
an alpha-crossfader)(+ platform specific codec info)
Live camera input (same as VJ mixer but with [pix_video], with
platform specific info on USB/firewire inputs what works & what doesn t)
VJ effects (using the various pix objects)
Basic 3D (that actually does something interesting, rather than just
show a sphere or a cube)
Basic movement tracking w/ [pix_blob]
GEM/video optimization/troubleshooting tips (see Troubleshooting
section of existing Pd FLOSS Manual) * MIDI tutorial
hardware:keyboards, sliders, etc,
objects: all MIDI objects
routing: input + output to/from devices or other programs * Patching strategies
Reusable abstractions ($0 etc)
GoP + other GUI creation strategies
Preset saving systems (Frank?) * Audiofile manipulation (Derek can provide examples, possibly also work
with www.pd-tutorial.com with permission?)
sfread, readsf, sfplay, etc
tables + tabplay, tabread, etc
oneshot playback without/with pitch shifting
looping without/with pitchshifting
granulation without/with pitchshifting
Extended objects ([xplay~], [xgroove~] are these stable? In my
experience, no ) * Realtime audio effects tutorial
delays: single tap, multitap, pitch-shifting, tuned comb filter, etc
filters: [hip~], [lop~], [bp~], [moog~], IEM lib filters
[vcf~]/[bp],[hp],[lp], difference between audio signal and message
controlled, building with ggee objects [bandpass],[llowpass],[highpass]
or [biquad~] (resources for coefficients?) * Sensor tutorial (HC?)
[hid]/[hidin]/[pduino]
simple circuit diagrams + photos (voltage divider examples:
potentiometer, photoresistor, etc)(hacked gamepads) * Networked data
netsend/netreceive
OSC
flash server
shell
python externals
others? * PDP/PiDiP
configuration info for OSX (+ poor performance disclaimer!)
basic VJ
networked streaming etc * Procedural Audio tutorial? (Andy?) * RJDJ tutorial? (Frank and the gang?)

28 March 2009

David Welton: Software Economics - Public Goods

To look at the economics of open source software, you have to start with the economics of software as a category, both proprietary and open source. Note: it should be perfectly obvious to everyone that open source software works, and works quite well for some things. This article is more about understanding the how and they why. Just to avoid any confusion... If you look at software as a product, it has a couple of defining characteristics:
  • It's difficult to keep people from sharing it. Not impossible, but not easy, either. It was already doable in the days of floppy disks, but with the rise of the internet, it has become nearly effortless. This means, in terms of economics, that it's "non excludable" - it's difficult to keep everyone from enjoying it once you've created it and started to distribute it.
  • If you give a copy of a program to a friend, it in no way detracts from your own use of the program. Quite the contrary, it may even make your use of it better, if, say, your friend discovers how to use a cool feature, or writes a handy extension. This is different from traditional goods like bicycles. If you loan me your bicycle, you can't use it to get around. In economics, things like software (or radio or over the air TV) are called 'non rivalrous' goods - many people can take advantage of them without ruining them.
What do you get when you combine something that's "non excludable" and "non rivalrous"? In economics, these are known as "public goods": http://en.wikipedia.org/wiki/Public_good - read the whole thing if you have a few minutes, it's what I'll be talking about. As per the article, "The Problem" as it were, is the free rider problem. Let's stop and look at a contrived example: Bob is an ex-dentist and really knows what it would take to write a great program for managing a dentist's office (or pick your own example... it's contrived, don't quibble about the details). He's also a good programmer, with the skills necessary to implement the program. He talks to a few of his dentist friends, and they're enthusiastic about the whole thing. Let's look at a few scenarios of how things might play out: Bob values his time at 10 dollars an hour, and it will take him 100 hours to complete the project, meaning the whole project would cost about 1000 dollars. One way things could work is that he could find a dentist friend who needs this program, and bill him 1000$ for his time and services, bang out the code, and release it as open source software. Bob gets his money, the dentist gets his code... and all the other dentists in town get it for free, which is bound to make the dentist who shelled out the money a bit irritated, given that he's a human, not a homo-economus, and doesn't like paying and see others get the same thing for free. Let's introduce another variable: the software is only really worth 200$ to the dentist - any more than that and yeah, it's helpful, but not worth that much money (And please stay with me, I know it's contrived, but keep in mind that the situation *is* possible, even if the numbers might be different). That means that if Bob wants 1000$ for his time, but the dentist will only pay 200$, then no transaction will occur! The software won't get written, Bob won't get any money, and the dentist will be worse off because he won't have the nice program, and neither will his dentist colleagues. One way things might still work is if the dentist rounds up some friends and they all contribute a bit, however, that's kind of a pain in the neck for everyone concerned - the dentist doesn't want to get into the software business and spend a bunch of time trying to chase his friends for money, and even if 10 dentists contribute, the ideal position to be in his the 11th guy, who pays nothing, and still gets the software for free. So it's in everyone's interests to not return the dentist's calls in the hope of being the 11th guy. Also, none of them gets the software until they're all on board. So, how to resolve this problem? The wikipedia page talks about introducing an exclusion mechanism, which in this case would be a copyright system so that Bob can sell a copy of his software for 100$ and be sure that it won't be open to everyone to use. This way, the dentists get the software for 100$ less than they value it at (200$), and as soon as Bob signs up an 11th dentist, he's making more than his time/materials costs, and is therefore coming out ahead! The dentists all know that they're paying the same price, so have no reason to grumble about free riders. In short, everyone is pretty happy. Of course, in the real world, things don't play out like that all the time. There are problems with the simplified example above, some of which are very evident: the cost of enforcing copyright laws, in an age when copying is extremely easy, is very high and potentially very intrusive. However, "intellectual property" is, by and large, a compromise solution that has had positive aspects, especially when you ignore the outliers like Microsoft, and look at all kinds of niche software vendors, who make a nice living, create good products, and have happy, satisfied customers. If you look at the other solutions to the free rider problem listed on the wikipedia page, we can see how they might be applied to the world of software.
  • Dominant assurance contracts
    Assurance contracts are contracts in which participants make a binding pledge to contribute to a contract for building a public good, contingent on a quorum of a predetermined size being reached. Otherwise their money is refunded. A dominant assurance contract is a variation in which an entrepreneur creates the contract and refunds the initial pledge plus an additional sum of money if the quorum is not reached. In game theory terms this makes pledging to build the public good a dominant strategy: the best move is to pledge to the contract regardless of the actions of others.
    This means that Bob goes out and gets a number of dentists to pledge 100$ to his dentist program, and if he doesn't raise at least 1000$, he'll give them each back 110$. So it's a clever solution that works out for everyone, but is still a lot fiddlier than the copyright system - Bob has to go sell the contracts and explain how things work to a bunch of people before he can get started. This might be doable with 10 dentists, but for a more mass-market sort of program, it would not be feasible.
  • Coasian solution
    a mechanism by which potential beneficiaries of a public good band together and pool their resources based on their willingness to pay to create the public good. Coase (1960) argued that if the transaction costs between potential beneficiaries of a public good are sufficiently low, and it is therefore easy for beneficiaries to find each other and pool their money based on the public good's value to them, then an adequate level of public goods production can occur even under competitive free market conditions.
    That sounds an awful lot like open source software, especially the kind espoused by groups like the Apache Software Foundation, where making free software is not a moral imperative, but a good way of producing something that is not necessarily a key business component. This has proven to work very well for infrastructure type code, as well as lots of developer tools. It is less proven as a way to develop end-user software - in the example above, it's not like Bob needs help to develop his system, or that the dentists really want to contribute - they just want a working program and don't want to get involved in its production.
  • Government provision This would mean that the government would be responsible for funding the production of open source software. I'm no free-market zealot, but I think the idea of the government being responsible for software products is not one I am entirely comfortable with. Of course, I do think the government has a role with places like universities, where people can do "research" in the sense of hacking on cool systems just to see what can be done, without necessarily having to be thinking of how to make a profit in the short to medium term. Software like BSD, Tcl, and plenty of other great stuff has come out of universities, meaning that in part it is ultimately funded by the government and taxes. The problem, though, is the process of refining those things down into something people are willing to buy. Would Bob go to a local government official to get a grant to produce his software? Why should Bob get the contract and not some other guy? Does the government official know enough about code or dentists to determine who should write the program?
  • Subsidies Subsidies might work to encourage software production, but would probably simply be abused. It's probably not as relevant as other potential solutions. What form would it take? 1$ off your taxes per line of code written? It would be difficult to place a value on anything, and might be quite difficult to implement.
  • Privileged group This, as the wikipedia page says, is an incomplete solution, and is less generally applicable. In terms of Bob, it might mean that instead of valuing his code at 200$, his wealthy dentist friend with a large practice really needs the code - it's worth 2000$ to him, and can pay Bob the full 1000$ to develop it out of pocket and still come out ahead, and he doesn't really care that much about the free riders because he's getting what he needs and the rest doesn't matter too much.
  • Social norms If Bob and the dentists live in a small town, and are all good friends, perhaps Bob could still release the software, and even though the other dentists could copy and use it for free, they don't, because they feel an obligation to Bob to help him out for the work he's done. Even though they could take advantage of it for free, they would feel bad about doing so, and so each chip in 100$, which after enough people contribute, is enough to cover Bob's costs. It's likely that anything distributed on a larger scale, however, will see more free-riding, and "please pay!" might not work out. And it's probably fairly distressful for a developer to make that jump, knowing he's at the mercy of other people's good will.
None of these solutions is perfect, and all, including exclusion in the form of intellectual property laws, or simply doing nothing at all, have problems of their own. Due to the very nature of software, this is somewhat inevitable, and the best we can do is come up with good compromises, and continue to reevaluate them as technology and society change (this is something that needs to happen with IP laws, for instance).

27 March 2009

David Welton: Software Economics - Public Goods

To look at the economics of open source software, you have to start with the economics of software as a category, both proprietary and open source. Note: it should be perfectly obvious to everyone that open source software works, and works quite well for some things. This article is more about understanding the how and they why. Just to avoid any confusion... If you look at software as a product, it has a couple of defining characteristics: What do you get when you combine something that's "non excludable" and "non rivalrous"? In economics, these are known as "public goods": http://en.wikipedia.org/wiki/Public_good - read the whole thing if you have a few minutes, it's what I'll be talking about. As per the article, "The Problem" as it were, is the free rider problem. Let's stop and look at a contrived example: Bob is an ex-dentist and really knows what it would take to write a great program for managing a dentist's office (or pick your own example... it's contrived, don't quibble about the details). He's also a good programmer, with the skills necessary to implement the program. He talks to a few of his dentist friends, and they're enthusiastic about the whole thing. Let's look at a few scenarios of how things might play out: Bob values his time at 10 dollars an hour, and it will take him 100 hours to complete the project, meaning the whole project would cost about 1000 dollars. One way things could work is that he could find a dentist friend who needs this program, and bill him 1000$ for his time and services, bang out the code, and release it as open source software. Bob gets his money, the dentist gets his code... and all the other dentists in town get it for free, which is bound to make the dentist who shelled out the money a bit irritated, given that he's a human, not a homo-economus, and doesn't like paying and see others get the same thing for free. Let's introduce another variable: the software is only really worth 200$ to the dentist - any more than that and yeah, it's helpful, but not worth that much money (And please stay with me, I know it's contrived, but keep in mind that the situation *is* possible, even if the numbers might be different). That means that if Bob wants 1000$ for his time, but the dentist will only pay 200$, then no transaction will occur! The software won't get written, Bob won't get any money, and the dentist will be worse off because he won't have the nice program, and neither will his dentist colleagues. One way things might still work is if the dentist rounds up some friends and they all contribute a bit, however, that's kind of a pain in the neck for everyone concerned - the dentist doesn't want to get into the software business and spend a bunch of time trying to chase his friends for money, and even if 10 dentists contribute, the ideal position to be in his the 11th guy, who pays nothing, and still gets the software for free. So it's in everyone's interests to not return the dentist's calls in the hope of being the 11th guy. Also, none of them gets the software until they're all on board. So, how to resolve this problem? The wikipedia page talks about introducing an exclusion mechanism, which in this case would be a copyright system so that Bob can sell a copy of his software for 100$ and be sure that it won't be open to everyone to use. This way, the dentists get the software for 100$ less than they value it at (200$), and as soon as Bob signs up an 11th dentist, he's making more than his time/materials costs, and is therefore coming out ahead! The dentists all know that they're paying the same price, so have no reason to grumble about free riders. In short, everyone is pretty happy. Of course, in the real world, things don't play out like that all the time. There are problems with the simplified example above, some of which are very evident: the cost of enforcing copyright laws, in an age when copying is extremely easy, is very high and potentially very intrusive. However, "intellectual property" is, by and large, a compromise solution that has had positive aspects, especially when you ignore the outliers like Microsoft, and look at all kinds of niche software vendors, who make a nice living, create good products, and have happy, satisfied customers. If you look at the other solutions to the free rider problem listed on the wikipedia page, we can see how they might be applied to the world of software. None of these solutions is perfect, and all, including exclusion in the form of intellectual property laws, or simply doing nothing at all, have problems of their own. Due to the very nature of software, this is somewhat inevitable, and the best we can do is come up with good compromises, and continue to reevaluate them as technology and society change (this is something that needs to happen with IP laws, for instance).

25 March 2009

Neil Williams: cross-building is still hard

OK, it's gone 2am and I'm still battling with what was meant to be a simple task - check the latest (unreleased) changes in tslib on my touchscreen device.

First problem was that I forgot that the balloon is running Lenny, so I suddenly needed the armel libc6 from Sid. OK, that's not bad, a bit of a pain to have to install it but less pain than creating a Lenny chroot to cross-build tslib - marginally.

Second problem was more awkward - turns out that emdebian-tools 1.6.1 has broken the more fragile cross-build support which carefully wraps broken libtool installations. I was intending to work out how to fix each one of those before Squeeze anyway. The fix for the workaround was relatively straightforward and will be in 1.6.2, due for release once I've had some sleep.

Third problem was something much older - turns out that this broken libtool wrapper had only been able to work for the default cross-building architecture since about emdebian-tools 1.4 or 1.5 and if asked to build for a different arch, it got the wrong symbols. Hmm.

The diffs for each of these changes appear simple but, as ever, identifying the cause of the bug was harder. (In this case, sometimes the error showed up as "C++ compiler unable to create executables" - thanks autotools, that's really handy to know; other times it showed up as ERROR, symbols from ./.libs/libfoo are ABI 4 but symbols from libc are ABI version 0 - still cryptic but at least it is entirely accurate.)

Still, I've now been able to test tslib 1.0-7 and it works just fine and I've got an extra upload of emdebian-tools 1.6.2 to make tomorrow. Ah well.

24 March 2009

John Goerzen: Review: David Copperfield

I finished reading David Copperfield on the Kindle a few days ago. This is a review of the novel, not the Kindle. I m not an English major, and so I m not going to pretend to be one. I m not going to discuss what themes the book touches on, what category it fits in, or generally dissect it to the point where it s more monotonous than fun. I read the book because I wanted to, not because I had to write a paper about it. I must say, first of all, that this has got to be one of the best books I ve ever read. The vivid descriptions of the characters were just fun to read. One particularly meek man was described like this: He was so extremely conciliatory in his manner that he seemed to apologize to the very newspaper for taking the liberty of reading it. Some of the scenes in the novel are amazingly vivid and memorable. The hilarious and tense scene towards the end where one of the main villains is taken down was one, and of course just about every scene involving David s aunt is too. Dickens is a master of suspense. He does it through subtle premonitions in the book. You might not even really notice them as you re reading. But it sure had an effect on me: I had trouble putting the book down, and stayed up later than I should have on more than one night to keep reading another chapter or three. Like any good book, this one left me to think even after I was done reading it, and left me wanting to read it again. Right now. There are some practical downsides to it, though. It was written in the 1850s, and some of the vocabulary and British legal, business, and monetary discussions are strange to a modern American audience. Nevertheless, with the exception of the particularly verbose Mr. Micawber, you can probably make it through without a dictionary, though one will be handy. I read it on the Kindle, which integrates a dictionary and makes it very easy to look up words. I learned that a nosegay is a bouquet of showy flowers. And that Mr. Micawber was fond of using words obsolete since the 17th century, according to the Kindle. If you remember that pecuniary emoluments refers to a salary, you ll be doing OK. The other thing that occasionally bugged me was that the narrator (David) would comment on some sort of gesture, or comment that wasn t very direct, and then say something like, But she didn t need to be more explicit, because I understood the meaning perfectly. Well, sometimes I didn t. Though I usually figured it out after a bit. I was never quite sure if Dickens was being intentionally needling to the reader, or if an 1850s British reader would have figured out the meaning perfectly well. But that was part of the fun of it, I think.

19 March 2009

Kartik Mistry: Debian Bug Reporting and More For Dummies


* It looks like people don t know how and when to report bugs to Debian BTS. Following are some steps for them: 1. Fire terminal, type reportbug . Follow instructions. Use reportbug-ng if needed! If you are not comfortable with terminal, firing a mail to submit@bugs.d.o with proper subject is fine. Look at example of any bugs. Its very easy. 2. If you are using Sid . Don t forget to report bug when they are encounters. 3. File a bug, rather than crying about maintainer not responding and blah blah. 4. While updating system to Lenny, Keep such documents handy. 5. Ask :)

17 March 2009

Adeodato Sim : When timestamp without time zone beats timestamp with time zone

I m the kind of guy that keeps a list of all the movies he s watched, with dates. Additionally, I m the kind of guy that used to keep such list in an SQLite database, and that keeps it in a PostgreSQL database now. Heh. I used to register just the day in which I watched a certain film. When moving to Postgres, I decided to record the time of day as well, which can come handy for those times where I d watch 2 films in the same day, in order to know which one came first. (I seem to have a small number of dates registered where I watched 3 films on the same day.) So, I went for a timestamp with time zone column. As its name seemed to promise, I was expecting for it to store the absolute timestamp of the event, plus the time zone it occurred in. But it doesn t work that way: a timestamp with time zone column only stores the absolute timestamp of the event, but not the associated time zone information. When returning the data to you, the event will always be in the local time zone, meaning that the only use for the with time zone part is that you can feed PostgreSQL dates in different time zones, and it will know to convert them all to absolute UTC before storing them in the database. This was a tad upsetting, because it meant I was actually losing information. For me, the most relevant information to store was the date of the event (as in, which day), and I was only storing the time for the purposes stated above. Should I move to a different timezone, either permanently or temporarily, some or all of the dates could very well be off by one day. The proper solution if you re such a pedant is to store in an additional colum the time zone, either as a symbolic name, or as a numeric offset. But I don t care that much, so I ve gone for a timestamp without time zone column, which solves the problem just fine: give me the date this event happened, in whatever time zone you happened to be at the time. By the way, one of my main objectives with keeping my list of watched movies in a database was to be able to quickly answer the question: What other films have I watched this actor in? Is a question that I make myself surprisingly often (because I ll know I ve seen a face before, but will not remember where), and an SQL statement is oh-so-much-more convenient than visiting an IMDB page and scan it for titles you think you ve watched.

16 March 2009

James Morrison: Recent Bands

13 Mar 2009
White Swan, Black Swan: nice vocals, I only caught a couple songs

The Donkeys
Decent band, fun to listen to. A good whale joke:
Two whales are sitting at a bar
one says to the other [long whale noises]
The other says, "man you are trashed."

Quick to get on stage and play

Phosphoressence
Good country rock band. Slow to start playing and some assholes decided to pop into the front of the crowd, they were tall so they blocked a bunch of peoples view. Then they gained an extra 3 people and started moving backwards. For once someone actually got inside my bubble.

7 Mar 2008 -- Red Devil Lounge
* "Three of" (good luck googling these guys) -- very good
* A, b, and C -- not good, the lead singers voice cracked a lot, they did look like they should be in the movie "That thing you do" (my first date was at this movie).
* Moonlight Sexy -- ok, Andy didn't like these guys
* Marcy Playground -- Great!

14 Mar 2008 -- Writers with drinks
S.G Browne with Breathers: A zombie's lament. The chapter he read was really funny. I think this was the best part of the night. The host was also really good, but the host could be described as slightly scripted talking out of her ass.

10 March 2009

Jonathan McDowell: Bachelor Pad

Translink are breaking the trains for 3 months at the end of March. This is manifesting as the line between Ballymena and Coleraine being entirely shut (it's only single track, so it's not like they can do one side at a time), but will hopefully result in a smoother, faster journey. Not much good for the 3 months when my journey goes from a single train ride to a train, bus, then another train ride. And gets longer by 20-30 minutes (so potentially 5 hours a day commuting. Yay!). I think not.

So I have rented a flat in Belfast, conveniently only 3 minutes walk from work. 3 month leases are hard to find so I have it for 6 months. I'm a bit freaked. I shouldn't be really; I lived alone when Katherine first moved back to NI. But that was in a house I'd been in for ages rather than somewhere entirely new to me. It proved its worth last night when we were able to walk to Do You Remember the First Time? in a couple of minutes though. Being in the city centre is damn handy, though I'm having to get used to the regular noise of traffic again. :)

(This post primarily a test of Drivel; it's not worth the hassle of dealing with Virgin or BT to get a broadband connection, so I'm going to end up continuing to use my Orange 3G dongle and trying to do things in local clients where possible.)

Next.

Previous.