The future of Panflute development

As probably surprises nobody paying attention to my (lack of) recent activity with it, I don’t have any plans to continue actively developing Panflute.

For starters, I’m doubtful whether there’s going to be much of a need for Panflute or something like it in the future. Panflute basically serves two functions: abstracting various music players’ RPC interfaces behind a common MPRIS-based front-end, and allowing said player to be controlled within a GNOME panel via an applet.

For the first, a lot of the music players out there in the Linux world today use MPRIS as their RPC interface, so there’s little need to stick another process in front of it with little to do other than serve as a pass-through proxy. Furthermore, recent versions of Rhythmbox and Banshee, two of the players with the largest user bases, have added MPRIS v2 interfaces in addition to (and eventually replacing, presumably) their original custom RPC interface. Today, a developer can support most of the players out there by writing a client that speaks MPRIS and MPRIS v2, which isn’t an unreasonable amount of work. Yes, there are a few players that still use a custom RPC interface, but development efforts would probably be better spent adding MPRIS support to them instead of using a separate application like Panflute as a translation layer.

For the second, the GNOME panel will no longer exist once GNOME 3.0 is released, which uses a different graphical shell, pretty much eliminating the use case for Panflute’s panel applet entirely. Similarly, upcoming versions of Ubuntu replace the primary GNOME interface with Unity, also eliminating the panel where applets would live. Even using the GNOME 2 interface instead of Unity, Ubuntu provides a notification area icon that basically acts as an MPRIS client itself, so there’s not much need to use Panflute in addition to that.

Finally, and perhaps most importantly, I’d simply prefer to spend my copious free time on things other than Panflute development. My motivation for working on Panflute has been rather low for a while, and after considering the (lack of) continuing need for it, it’s sunk even lower, to the point where I really don’t see myself doing much else with it.

That’s not to say the project is necessarily dead, per se, if someone were to step up and effectively take over maintenance and development. There’s no candidates for that at the moment, though; Panflute has for the most part been a one-man show. If someone were to volunteer, I’d need to see some contributions made through patches and bug management before I felt comfortable handing control over. That’s assuming someone didn’t just decide to fork the project and go off on their own, which I’d also be OK with, not that my permission would be needed for that anyway.

Panflute 0.7.0 released

Panflute 0.7.0 has been released, with lots of improvements. Panflute 0.7.0 adds several new features, such as the ability to control the player’s volume, dealing sensibly with multiple players running simultaneously, better support for pausing and stopping playback, the ability to seek by using the mouse’s scroll wheel on the time display, and the ability to remove ratings from songs. It also adds support for four more players: Clementine, Decibel, Pithos, and Qmmp. And in case that’s not enough, there’s also lots of bug fixes, detailed in the release notes.

Introducing panflute-tests

The bad news is that I won’t be releasing the next version of Panflute at the end of the month as I had planned; that’s been pushed back to the end of October. That’s because it took much longer than I was expecting to get a new backend feature working: panflute-tests.

As of ths writing, Panflute supports 15 different music players, with even more planned: Amarok, Audacious, Banshee, Exaile, Guayadeque, Listen, MOC, MPD, Muine, Quod Libet, Rhythmbox, Songbird, VLC, XMMS, and XMMS2. Manually testing Panflute with the latest version of each is impractical; expanding that testing to include the last n versions of each of those is completely unreasonable. As a result, I had largely been slacking off doing proper testing, meaning that bugs, especially when the new version of a player changed its interface somehow, were common.

panflute-tests is a tool designed to automate the process of compatibility testing as much as possible. It allows a developer to define a series of test configurations, which are basically a particular installation of a particular version of a player, such as Banshee 1.7.4 installed under $HOME/players/banshee-1.7.4. For each defined configuration, panflute-tests will initialize the player with a known “music” collection and run a series of tests against it. The tests themselves are simple; for example, one checks that when the Play, Pause, and Stop commands are issued, the player responds by reporting the appropriate state change.

Even though each test is simple, the ability to automate running them against lots of configurations makes overall compatibility testing much more thorough and repeatable. Already, it’s discovered bugs that hadn’t been reported to the Panflute bug tracker, such as not retrieving metadata from recent versions of XMMS2 correctly.

Running panflute-tests yourself

panflute-tests is very useful, but also very dangerous. Running it will destroy any configuration settings you have for the music players installed on your system. This is by design; it’s essential to start each test with the player in a known state, so configuration settings get rewritten to load a specific music connection. For this reason, if you insist on running panflute-tests yourself, I implore you to do so in a virtual machine dedicated to using panflute-tests. I myself have a VM of Ubuntu Lucid where I currently have approximately 60 different players installed. As an added precaution, panflute-tests will refuse to do anything unless you specify the deliberately ominous --destroy-my-data option on the command line.

panflute-tests configuration

Adding a new test configuration is straightforward: click the Add button and fill in the player name, its version, and the prefix under which it was installed. I recommend installing each player to be tested to a unique prefix; I’ve been using $HOME/players/name-version, so that in the screenshot above I have Amarok 2.3.1 installed under /home/paul/players/amarok-2.3.1. At the very top of the window, you’ll also need to specify the installation prefix of Panflute itself.

That’s really it as far as setting up a test configuration goes. panflute-tests takes care of the ugly, nasty, difficult work of editing each player’s configuration settings appropriately before a test, or dealing with any other trickery to make everything work. Select the tests you want to run and click Run, then wait for the results.

panflute-tests result

Each test has three possible outcomes. PASS means it worked, FAIL means it didn’t, and SKIP means the player doesn’t support the feature being tested at all. In the event of a FAIL result, panflute-tests will show the exception backtrace that triggered the failure.

In the above screenshot, we see that the Seek test FAILed for Amarok 2.3.1. It turns out that this is because of quirky behavior of Amarok itself rather than a bug in Panflute — during a seek, Amarok’s reported elapsed time jumps around a bit before it settles down, and this confuses the checks that panflute-tests is making. That’s why panflute-tests lets you add a comment to any test or configuration. This is very useful to document which tests are known to fail due to no fault of Panflute’s. Also in that screenshot, we can see that the combined set of tests for Amarok 2.3.2 PASSed, suggesting that this quirk of Amarok was fixed in the current version.

As an undocumented feature, it’s possible to use panflute-tests to start a player under its test configuration without running any tests. To do this, invoke panflute-tests along these lines:

panflute-tests --subprocess Amarok instdir ~/players/amarok-2.3.1

where instdir is the Panflute installation prefix, ~/players/amarok-2.3.1 is the player installation prefix, and Amarok is the name of the player. This is sort of an abuse of how panflute-tests works internally, but I’ve found it useful when trying to diagnose why a test case is failing. Be warned that it will still destroy your data when invoked in this manner.

As another undocumented feature, panflute-daemon’s stdout and stderr get redirected to /tmp/panflute-daemon.out and /tmp/panflute-daemon.err during a test. This is also helpful when trying to figure out why something didn’t work.

Maverick and future plans

The PPA for Panflute now has builds for Maverick in addition to Jaunty, Karmic, and Lucid.

Work on Panflute 0.7.0 has been sporadic lately, but it is happening. The big thing I’m working on right now is a way to test Panflute’s capabilities with the wide range of players it’s trying to support — with 15 different players, and multiple versions of each one, it’s completely impractical to manually test Panflute against each. Some of this has already landed in the source repo, but it’s in an extremely early stage at the moment. It’s also dangerous — there’s a reason the test tool refuses to do anything unless you explicitly ask it to --destroy-my-data. (I’ll write about how to use it correctly after it becomes at least half-baked.)

Most of the other plans for 0.7.0 involve clearing out the backlog of bugs. I’m hoping to release 0.7.0 by the end of September.

Panflute for Lucid

The Panflute PPA now contains packages built for Lucid in addition to Karmic.

Panflute 0.6.2 released

Panflute 0.6.2 has been released; all users are encouraged to upgrade. This release fixes several bugs, including a creeping CPU usage bug and compatibility problems with Banshee and Exaile. It also includes four new translations: Czech (cs), French (fr), Dutch (nl), and Portuguese (pt). See the release notes for more details.

Panflute 0.6.1 released

Panflute 0.6.1 has been released. This version adds support for rating songs in Banshee 1.5.3 or later, and fixes a few bugs. It also expands the types of song information that can be displayed in the applet.

Panflute 0.6.0 released

Panflute 0.6.0 has been released. This release adds support for several new players, namely Guayadeque, Listen, MOC, and Songbird, as well as older (1.4) versions of Amarok and recent (0.3) versions of Exaile. On top of that, it’s now possible to seek within the current song from the applet, and the song information display can be customized. There’s also assorted bug fixes, and new translations for Spanish (es) and Polish (pl).

Panflute 0.5.3 released, Karmic PPA imminent

Panflute 0.5.3 has been released. This version fixes a few minor bugs. It is also the first release to have packages for both Jaunty and Karmic uploaded to the PPA.

Panflute 0.5.1 released

Panflute 0.5.1 has been released! This release contains no new features but fixes several bugs. A list of bugs fixed in this release can be found in the release notes. All users, especially those who use Panflute with Quod Libet or VLC, are encouraged to upgrade.

Panflute 0.5.0 released

Panflute 0.5.0, the successor to Music Applet, has been released. The source can be downloaded from Launchpad, and I’ve also set up a PPA for Panflute to make installation even easier (at least for users of Ubuntu and other Debian-based distributions).

Panflute 0.5.0 is essentially feature-compatible with Music Applet 2.5.1. There are only two notable differences in terms of functionality:

  • The applet now supports two-row layouts for fat panels, and offers greater flexibility in how widgets in the applet are arranged.
  • The time display can be switched to show remaining time instead of elapsed time.

Under the hood, of course, it’s a complete re-write of the code, splitting the music player abstraction layer off into a separate process, which can be used by other programs without needing to install the applet. This post explains the rationale for this fundamental change in more detail, but from the casual user it should (hopefully!) be invisible.

Unfortunately, Panflute doesn’t currently have any translations into other languages. I plan to use Launchpad to manage translations, but haven’t yet had a chance to set it up.

If you find any bugs in Panflute, please report them via Panflute’s bug tracker, also hosted on Launchpad.

Never give an applet a tooltip

The following code creates a GNOME panel applet with three things in it: some text, a button, and some more text. The button has a tooltip, and everything else has a different tooltip. However, there is a bug here. Can you find it?

#! /usr/bin/env python
 
import gnomeapplet
import gtk
 
def applet_factory (applet, iid):
    applet.set_applet_flags (gnomeapplet.EXPAND_MINOR)
    box = gtk.HBox ()
    label1 = gtk.Label ("blah blah blah")
    button = gtk.Button ("Do something")
    label2 = gtk.Label ("Bob Loblaw")
 
    applet.set_tooltip_text ("Stuff")
    button.set_tooltip_text ("(doesn't actually do anything)")
 
    box.pack_start (label1)
    box.pack_start (button)
    box.pack_start (label2)
    applet.add (box)
    applet.show_all ()
 
    return True
 
if __name__ == "__main__":
    gnomeapplet.bonobo_factory ("OAFIID:name_of_some_applet_factory",
                                gnomeapplet.Applet.__gtype__,
                                "test",
                                "0.0.0",
                                applet_factory)

(Hint: re-read the title of this post.)

To make the applet easy to use, we consider Fitt’s law, which deals with how easy or difficult it is for the user to move the mouse pointer to a particular position on the screen. Specifically, the easiest position is obviously the current position, since no movement is required. Second easiest are the corners of the screen: the user just shoves the mouse in the right direction. Since the pointer stops at the edge of the screen, it’s impossible to overshoot. Third easiest are the edges of the screen, for a similar reason.

Since panels live along the edge of the screen, we want to make sure our button is positioned precisely at the edge of the screen, making it easier to click on. That’s why the above code sets the EXPAND_MINOR flag, telling the applet to fill all available room between the edge of the screen and the edge of the panel. Our expectation is that the button will then be stretched to fill this space.

However, it doesn’t! There’s a one-pixel border around the applet’s contents. If we push the mouse pointer to the edge of the screen, we wind up overshooting the button by one pixel. So close, yet so far.

(Fun fact: earlier versions of Windows suffered from a similar problem. The Start button was a pixel or two away from the corner of the screen, so clicking in the corner didn’t activate it. This was fixed in Windows XP, or possibly earlier — I don’t have ready access to a Windows 2000 machine to check.)

The cause of the problem is hard to see, and took me a good amount of debugging to find: adding a tooltip to an applet causes that one-pixel border to appear! Remove the tooltip, and the button gets those two extra pixels that let it fill the entire panel along the minor axis. One wouldn’t expect setting a tooltip to affect widget layout, but it does.

To get the effect we want, we set the tooltip on the box used to pack the widgets, instead of on the applet itself. The one-pixel-border effect only happens with the applet itself, for reasons I can’t explain. So we replace this:

    applet.set_tooltip_text ("Stuff")

With this:

    box.set_tooltip_text ("Stuff")

Now all is right with the world, where “world” is defined as “Panflute bug #412309“.

(Pedant’s corner: another bug in the code above is that middle- and right-clicks on the button don’t get propagated to the applet for handling there. Fixing that requires subclassing gtk.Button to override do_button_press_event and return False if event.button != 1. But that’s much easier to figure out. I omitted that detail from the example above for simplicity’s sake.)

Panflute

Panflute is the new black Music Applet.

Let me explain.

Panflute is slated to be the successor to Music Applet. Its fundamental architectural change is the complete separation of the part that draws the panel applet from the part that figures out how to talk to the backend music player. By “complete”, I mean that Panflute makes them entirely separate programs. This opens the possibility of other software also using the Panflute backend instead of figuring out its own way to talk to a dozen different music players. A panel applet is just one possibility — you might want a desklet, or whatever GNOME 3.0 will replace panel applets with, or an alarm clock, or something else I can’t even think of.

The goal of the Panflute backend is to make everything look like it has a nice, clean MPRIS interface. MPRIS is great because it specifies a common interface for programs to talk to music players. MPRIS isn’t so great because many popular players (such as Rhythmbox and Banshee) don’t use it, and many players that do implement it either deviate from the spec in some areas (such as Audacious) or have some odd quirks about their interpretation of the spec (such as Amarok). The Panflute backend papers over all these issues, presenting a single, common, consistent interface, regardless of what player is actually running. It also adds some (clearly marked) extensions to MPRIS to provide features not available in MPRIS 1.0, such as setting metadata (particularly ratings) for the current song, or having a convenient way to get updated position information without having to resort to polling.

Panflute also provides a panel applet to replace the old Music Applet. At this time not much has changed feature-wise, but by doing a ground-up reimplementation, I’ve been able to throw out a bunch of legacy code to work with now-fairly-old libraries and to redesign things to support more flexible layout of the applet’s content, such as the oft-requested support for fat panels.

Perhaps most importantly, however, is the fact that I’m using Launchpad to host development of Panflute instead of doing things directly off of kuliniewicz.org. This means I’ve now done something I should’ve done a long time ago and started using a proper bug tracker instead of relying on e-mail. Finally.

The plan for now is to get Panflute up to feature-parity with the most recent release of Music Applet and make that a 0.something release. The 1.0 release will try to include as many feature requests from Music Applet as I can manage, as well as a testing tool to help verify that the code that handles talking to each music player works as expected, and to map out what functionality isn’t available. (Hey, that’s another thing that can exploit the applet/backend separation!) The 1.0 release should also make sure those player support modules implement as much of the MPRIS spec as possible; so far I’ve been focusing on the /Player object (which the applet makes heavy use of) and largely ignoring the /TrackList object (which it ignores completely). Obviously, for the Panflute backend to be generally useful for other developers, it needs to be full-featured.

I really ought to formalize the above paragraph a bit and get a proper blueprint for future development up in Launchpad….

Anyway, the Panflute code hosted on Launchpad is functional, with all applet features except pop-up notifications implemented and backend support for Rhythmbox, Banshee, Amarok, Audacious, Muine, and VLC implemented. There’s still some rough edges, particularly how the applet doesn’t yet bother to start the backend process, but those issues will be easy enough to fix. (And now that there’s an actual bug tracker, you can file a bug if something is amiss and/or missing.)