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.

Win32 Python: Getting all window titles

This post shows how you can retrieve all window titles in Microsoft Windows using Python’s ctypes module. Moreover, it also acts as a ctypes tutorial, showing how to create and use callback functions.

The following is the full code. Keep reading if you want to understand how it works. (Note: If you are reading this as a ctypes tutorial and are having trouble following the explanation, you may want to go through my previous tutorial first.)

import ctypes

EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible

titles = []
def foreach_window(hwnd, lParam):
	if IsWindowVisible(hwnd):
		length = GetWindowTextLength(hwnd)
		buff = ctypes.create_unicode_buffer(length + 1)
		GetWindowText(hwnd, buff, length + 1)
	return True
EnumWindows(EnumWindowsProc(foreach_window), 0)


Continue reading

News flash: MP3 has improved in the last ten years

I’m surprised at how good MP3 can be. I’ve just tried a website that lets you do ABX tests between 128 and 320 kbps MP3 files. Presumably 320 kbps is meant to represent the “known transparent” sample (which should be true for my case). After getting one correct answer out of three, I stopped because it just wasn’t going to work out.

What’s surprising is not really the bitrate (I have previously ABX-tested Vorbis q2 (~96 kbps) and found it to be almost transparent); it’s that MP3 encoders have gone a long way since the last time I tried them. I guess most of their notoriety is carried over from the Napster era which, come to think of it, ended around ten years ago.

On a related note, MP3 and H.264 share an ironic trait: both are patent-encumbered, yet the best encoders for for them are free / open source software (LAME and x264). The difference is that MP3 is inferior to pretty much any of the other formats in use today.

Obscure-app-I-use of the day: atool

atool is the command-line equivalent to WinZip-style programs—and it just works.

Most importantly, the aunpack tool (for extracting files) will first check the number of items in the archive root. If there is only one item (a directory or a file), it gets directly extracted to the target directory. If there are more than one, they are extracted to a new directory.

For example, if A.tar.xz only contains fileA, aunpack A.tar.xz will extract fileA to the current directory. If B.tar.xz contains fileB1 and fileB2, aunpack extracts them to a directory called B. This has saved me countless times from extracting truckloads of files to my home directory.

WebKit trademark filed in the US, no big deal

Hm, I missed the news about Apple filing a US trademark for WebKit earlier this May. I think it’s not a big deal.

A lot of free software project names are trademarked by the authors in some part of the world. Most are used defensively so that others cannot file the same trademark, but some are used for preserving brand identity (see Iceweasel).

In the worst case, projects have changed names over trademark or even non-trademark name clashes. Phoenix→Firebird→Firefox, Gaim→Pidgin, and Ethereal→Wireshark are three high-profile examples.

If the WebKit trademark is granted, depending on how Apple decides to guard it, others in the US will probably go back to the KHTML name. Considering there are other big stakeholders in the WebKit world now (Google being the biggest one), I don’t think Apple will risk fragmentation, but who knows.

In my opinion, among “intellectual properties”, trademark is likely the least of our concern. I could be wrong though; I haven’t seen much discussion around it.

pasink, making PulseAudio sink management less painful

I have three sound cards (on-board, HDMI, and external) and the only sane way to manage them was through pavucontrol. pavucontrol is amazing, but I wanted a command-line app that I can use in keyboard shortcuts and udev rules.

This bothered me enough that I created one myself. If you’re interested, check out pasink (direct link to code). It’s a Python wrapper to pacmd, the PulseAudio console. I’ve thought of using libpulse through Vala, but it’s probably overkill for now.

The script lets you do things like setting volume on each card and setting a particular card as the main output device. I suppose doing the same on input devices would be useful, but I skillfully dodged that responsibility by naming the app “pasink”. It’s not that I don’t see the value; I simply don’t have the motivation.

If you want to extend pasink to also cover audio sources, feel free. You’ll have to rework the interface; perhaps let the behaviour depend on whether the program is run as “pasink” or “pasource”.

If you get a PUSHL-related error…

If you’re compiling a piece of code and getting an error message saying something about PUSHL or “invalid suffix for PUSH”, it means you’re feeding x86 assembly code to an x86_64 assembler.

Possible causes:

  • The code you’re trying to compile really does contain x86 assembly, perhaps inlined from C, but you’re targeting x86_64.
  • Your toolchain somehow contains a mix of x86 compiler and x86_64 assembler. Try cleaning up your PATH.


In a bizarre turn of events, GNOME’s accessibility options suddenly made my desktop unusable.

If you hold down the Shift key for a number of seconds, GNOME will helpfully turn on the slow keys accessibility option, which causes each key press to require around one second to register. Needless to say, the result was massive confusion.

For reference, in MS Windows, an accessibility option being turned on via keyboard shortcut is followed by an obnoxious alert sound and a message box telling you what just happened and how to turn the option—plus optionally its shortcut—off.

strxfrm in Vala

Here, let me save you some time: string.collate_key.

I spent hours trying to get Posix.strxfrm to work and still failed. It was actually so much easier to write a simple strxfrm wrapper in C and use it as an external function. While admiring my work on this wrapper, I found GLib’s g_utf8_collate_key, which in Vala translates to the aforementioned string.collate_key.

By the way, I’ve just realised that strxfrm stands for string transform.

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.]