Tag Archives: exaile

The Moodbar audio visualisation method

One of the niftiest legacies of the old Amarok music player (version 1) is the Moodbar visualisation method. The idea behind it is simple: take the source audio signal, analyse it, and create a colourful representation of the sound as a timeline.

[Image showing Exaile with Moodbar visualisation, in which the original seek bar is replaced by a colourful-looking bar]

Exaile with Moodbar replacing the standard seek bar

Back in 2009, Solyanov Michael created an external plugin to add Moodbar support to Exaile, and at some point it was imported into the Exaile tree. Now that we’re upgrading Exaile to GTK+ 3, I have been rewriting the plugin’s UI code to use Cairo instead of GDK drawing functions, which don’t exist anymore. (Unfortunately I don’t think I’ll have the time and motivation to implement all features of the existing plugin.) The above screenshot shows a sneak peek of how the new UI currently looks like.

What do the colours mean?

Moodbar is explained in a 2005 paper by Gavin Wood and Simon O’Keefe, which presents a number of algorithms for visualising audio signals. Specifically, the Bandwise Spectral Magnitude method is the one implemented as Moodbar.

Long story short, for each point in the timeline, the red channel represents low frequencies, green represents mid frequencies, and blue represents high frequencies. In practice, however, it is often difficult to imagine what an audio segment will sound like just based on its colour. The only thing you can pretty accurately guess is the audio level based on colour intensity (bright=loud, dark=quiet).

I’ve prepared a few Moodbar examples with playable audio for you to see this in action. Some of the samples (Hypocrisy, What Is Love) are pretty good and show all sorts of colours differentiating song sections. Some are less exciting, either because the song mostly uses a single instrument (Spring) or because the song is relatively monotonous (Max).

Current support in media players

To my knowledge, there are only three actively-developed media players with Moodbar support, all of which are based on Amarok 1 to some degree: Exaile, Amarok 2, and Clementine. Ironically, Amarok 2’s Moodbar support is the least integrated; you need to manually scan your files, whereas Exaile and Clementine do this for you as they play individual files.

Currently Exaile and Amarok 2 still rely on the old, GStreamer 0.10-based Moodbar program. Clementine seems to have integrated Moodbar into their own code and is using it as a library. Their latest release is still using GStreamer 0.10, but their development tree already contains a GStreamer 1.x-based Moodbar.

Future

Right now we are focusing on finishing the GTK+ 3 port of Exaile, which includes getting the Moodbar plugin to a reasonable state. The basic Moodbar functionality is ready; I just have to implement a fallback UI for tracks that have not been or cannot be scanned for whatever reason.

Other Moodbar-related tasks on my radar (read: may or may not happen):

  • Steal split Clementine’s new Moodbar code into a separate library so that Exaile and other media players can make use of it. I have the code sitting ready to be published, but it still needs more testing, especially since I’ve just found out that it produces different output to the original Moodbar program.
  • Add some of the old features that don’t make the cut to the GTK+ 3 port (darken should be doable; waveform will be tricky, given the way the new drawing is done).
  • Add support to share the Moodbar cache with Clementine. Not terribly useful, to be honest.
  • Do more research to find a better timeline visualisation method.
Advertisements

Exaile dropping the 0.x versioning

The next version of Exaile, which was to be version 0.3.3, will be version 3.3.0. We feel that the 0.x versioning was more confusing than actually useful or representative of the development process; in addition, the new versioning avoids long version numbers like 0.3.2.1.

In related news, Exaile 3.3.0 is going to be released soon. The RC is already out; please help us test it and iron out last-minute bugs.

Why there is no Python 3 / GTK+ 3 / PyGI version of Exaile

Exaile still uses PyGTK, which in turn depends on Python 2 and GTK+ 2. Why haven’t we upgraded?

  • Python 3: Not even sure PyGI supports it yet. Either way, needs PyGI.
  • GTK+ 3: Needs PyGI.
  • PyGI (a.k.a. new PyGObject): We’ve been trying. It segfaults randomly. And debugging segfaults from a Python program is… hard.

Update (2015-11): It’s happening; we’re slowly porting Exaile to PyGI. It will be using GTK+ 3 and GStreamer 1, but will still be on Python 2.

Shoutcast support broken, removed in future Exaile

If you’ve been using Exaile’s Shoutcast plugin, you would have realised that it hasn’t been working for a while now. This is due to a change in the SHOUTcast directory API.

However, SHOUTcast directory support is not coming back. The VLC developers explain in detail the problems that also prevent us from complying with SHOUTcast’s terms of service. The specific wording in the terms makes me believe that we will never see an acceptable solution, and that makes the issue of fixing the plugin a moot point. Following what VLC and Amarok have done, we have removed SHOUTcast directory support from Exaile.

Note, however, that Shoutcast/Icecast streams still work as long as you know the stream URI. It’s just the directory that is not working; for the time being, you can use the Icecast Web-based directory for this purpose.

In the future, we would love to switch to the Icecast directory, but their documentation seems a bit sketchy. If you would like to help with this, feel free to contact us through IRC or at the wishlist report. There is an Amarok script that you may be able to use as reference.

Meanwhile, I have removed the Shoutcast plugin from Exaile’s list of installed plugins. The outdated code is still in the source tree, but it will not be installed by our makefile.

[Update: I am was working on an Icecast directory plugin. It’s literally half-working (I can get genres but not individual stations, still figuring out why). For this plugin I’m screen-scraping the website because the actual YP directory seems to be incomplete.]

[Update 2: I’ve stopped working on the plugin for now as I’m occupied with something. Apparently there’s a working Icecast plugin in the bugtracker somewhere; I haven’t tested it.]

EBML/Matroska parser for Python

This post explains a Python EBML parser that I wrote. (EBML is Matroska‘s binary “markup language”.) It is implemented as a single-file library and is available under a free software licence.

Background

I’ve been working to implement Matroska (mka, mkv, webm) tag-reading support in Exaile. Mutagen—the tag library that we use—currently doesn’t have this feature, so I looked elsewhere.

Choices

Previously, I had a working solution using hachoir-metadata, but it doesn’t really make sense to depend on another large tagging library when we’re already using Mutagen. To make matters worse, I accidentally deleted the branch during our recent Bazaar upgrade problem.

I started shopping around for other possible solutions and found videoparser, which seemed quite nice and compact. It’s still a different library, though, and it doesn’t seem to be packaged in Debian.

I was considering just using it anyway for yet another temporary hack when I chanced on MatroskaParser.pm, a Perl library written by “Omion (on HA)”. It’s only 816 lines of Perl; discounting the README and the Matroska elements table, we’re looking at less than 450.

Solution

I decided to translate MatroskaParser.pm into Python. Despite the horror stories out there about Perl, this particular code is written in a style that is extremely readable if you’re somewhat familiar with the language.

Well, I’ve finished the porting: 250 lines of EBML parser written in Python. Parts of MatroskaParser.pm that are not relevant—mainly the validity checker and the Block parser—have been removed, and the output data structure has been simplified. The next job is to actually extract tags out of the structure.

Matroska tags

Matroska tags are quite different from MP3 and Vorbis tags, in that they’re not just a flat list of key-value pairs. Consider the following snippet.

[{'SimpleTag': [{'TagName': ['TITLE'],
                 'TagString': ['Light + Shade']},
                {'TagName': ['ARTIST'],
                 'TagString': ['Mike Oldfield']}],
  'Targets': [{'TargetTypevalue': [50]}]},
 {'SimpleTag': [{'TagName': ['TITLE'],
                 'TagString': ['Surfing']}],
  'Targets': [{'TargetTypevalue': [30]}]}]

There are two types of tags in this example. The first (target type: 50) explains the album (title: Light + Shade, artist: Mike Oldfield), while the second (target type: 30) explains the track (title: Surfing). Translating this structure into tags that Exaile can understand is not hard, just needs a bit of planning.

By the way, notice that Matroska makes implementing album artists / compilation albums very intuitive: you can have an artist tag at album level, and another at track level. There are even other levels specified. As a further example, because Light + Shade consists of two CDs labelled Light and Shade respectively, you could use them as the titles at level 40 (between album and track); however, this is not common practice.

Another tricky part is getting the track length out of the structure. Under /Segment/Info, you’ll find something like

[{'Duration': [14821615.0],
  'TimecodeScale': [22674]}]

At first I randomly assumed that the duration was specified in seconds, and got around 171 days as output, which is obviously wrong. Apparently you need to apply this formula to get the length in seconds:

Length = Duration * TimecodeScale / 10^9

Note that TimecodeScale may be omitted; it is one of the few important elements with default values (1,000,000 in its case).

Code

The code is now available in Exaile’s repository. It’s licensed under GPL 2+ with the standard Exaile exception, although I will consider relicensing it if there is interest.

Notice that the last 100-or-so lines make up the Matroska tagging part. Depending on your needs, you may need to expand the list of elements based on the Matroska specification. There are also 40 lines of code that subclasses the parser to use GIO to read the files; you may want to remove this chunk of code if it’s not relevant to you.

Future

Matroska read-only tag support will be in Exaile 0.3.2. Maybe one day I’ll add write support and integrate the whole thing into Mutagen, but don’t count on it. If anyone wants to do it, I’m more than happy to help.

What about WebM?

Funny how I made this post shortly before WebM was announced. Coincidence? Yes, unfortunately; I’m not as cool as the Mozilla and Opera people, who were let in on Google’s secret.

At this point, the WebM container is mostly just a subset of Matroska (the only incompatibility I’ve noticed is the change in doctype, from matroska to webm). As far as I know, they use the exact same EBML structure for tags, so there’s no reason Exaile or this code shouldn’t be able to read tags from a WebM file.

GIO tutorial: File operations

Recently I ported Exaile’s Files panel to use GIO instead of Python’s os module. The reason is simple: remote browsing.

Yes, you can now browse an SMB share or an SFTP server through the Files panel. Just mount the remote filesystem with gvfs-mount and enter the URL into the location bar. Previously Aren ported Exaile’s core to GIO as well, so remote files can be played just fine.

This is the kind of convenience you get out of using GIO/GVFS. In this article I’ll briefly explain what GIO is and how to do some basic file operations—similar to what the Files panel does—using GIO.

Screenshot of Exaile browsing and playing a file through GIO/GVFS

Note: This article is part of my ongoing GIO tutorial series, which currently consists of: (1) File and path operations (this document); (2) File IO; and (3) Launching files.

Continue reading

Using Ex Falso from Exaile

[Update: This post is out of date; the plugin has been removed because it doesn’t work anymore. It depended on some internal Ex Falso API which has changed, and I’m too lazy to fix the plugin considering I wrote it only as an experiment.]

Many Exaile users like Ex Falso, which is one of the most comprehensive tag editors in the GTK+ land. In fact, the tag editor in Exaile 0.2.x (developed by Ville Lindholm as part of Kesäkoodi 2007) was made to resemble it. This tag editor unfortunately did not make the transition to 0.3.0, which was released with a very simplistic tag editor.

For 0.3.1, Aren plans to have a tag editor that is as powerful as—but less complicated than—Ex Falso and the old tagger. The discussion in #exaile piqued my interest, and I decided to start working on a plugin that lets Exaile use Ex Falso as its tag editor, an idea that has been discussed several times before.

Screenshot of the Ex Falso integration plugin for Exaile

It seems to work quite well now. There were a few things I needed that Ex Falso’s standard API wasn’t designed to do, but they weren’t hard to work around.