Friday, November 30, 2007

Audio from YouTube in three steps

Needed packages: youtube-dl and mplayer. XXXX is the video ID on YouTube. You can find this out by looking at the URL of the video for which you want to get the audio.
  1. youtube-dl http://www.youtube.com/watch?v=XXXX
  2. mplayer -dumpaudio XXXX.flv
  3. mv stream.dump XXXX.mp3
Works for me. You can check if the file is really an mp3 file or if you still need to convert it from some other obscure format by running file stream.dump before renaming the file. Of course, this also works for mms:// streams with passing the mms:// URL to mplayer and using "-dumpstream" if you want the full video (or only -dumpaudio if you don't care for the video, as above).

Wednesday, November 28, 2007

The Kiss Principle: SOAP vs REST

Yesterday at university, we had a little talk about the pros and cons of SOAP. Well, not really, but SOAP was mentioned in one of the presentations, and so the professor suggested "The S stands for Simple". As he promised, it really describes the overengineered-ness of SOAP. I'm probably more the kind of REST fanboy, because it uses a widespread protocol (HTTP) and uses many of the features already present in the HTTP protocol without reinventing the wheel. What if a services moves? Do a HTTP redirect! What if there is no such service? 404! Error handling? If the error happened because of the input data, do a 4xx "client error", if not, do a 5xx "server-side error". It's simply following the Kiss principle.

Nobody likes writing wrappers, "creating" interface metadata that has to be parsed again to know how the interface looks. After all, doing sophisticated descriptions of interfaces will not automatically upgrade clients if you decide to revisit your public APIs. On the contrary, you have to re-generate (hopefully not rewrite by hand) the meta description of your API, and the client has to re-parse, re-generate or otherwise process this generalized description to finally redo their client-side code. On the other hand, when a REST-based API changes, you simply update your client-side code to work with the new API (and data structures, if they change too) and don't have to do much code generation and other "bureaucratic" code-generating nonsense.

HTTP already provides most things you expect from web services, and for really simple APIs (like the YouTube API), you can easily do "web service clients" with some http library and XML-parsing code (or not even that, but only JSON or even plaintext). In Python, I've already done this in python-youtube. The libraries I used: urllib2 and minidom from the xml.dom package - both included in the Python Standard Library. It surely is easier maintainable than, for example, with Python Web Services.

What I really want to say is that if you're doing public APIs, why not simply do it with REST instead of SOAP/Web Services (that is, if you're the provider of these services - you probably can't choose when you are interfacing with web services/APIs written by someone else)?

Wednesday, November 21, 2007

News from the Windows world

For compiling Tennix, doing some Windows-only work, testing website in IE6 and other tasks that require Win32, I still have a Windows 2000 installation that I use and update occassionally.

The last Sun Java update was a very pleasant surprise, as the update box did advertise OpenOffice.org (the MS Office competitor that has been bootstrapped and is now sponsored by Sun Microsystems). So, here's Sun using its leading(?) position in the Java JVM market to push another product that directly competes with Microsoft products.

I, for one, welcome this, as OOo has the advantage of being open source, and free as in beer. Did I mention you can easily export your documents into PDFs in OOo without the need for 3rd party software? I have yet to see this feature in Microsoft Office, but I think the last MS Office version I used was Office 2003 or so and they might have included that feature since then. Probably the most important reason for OpenOffice.org is the open, patent-free file format. Anyway, here's a screenshot of the Java Updater:


Another screenshot I want to share with you is related to wavbreaker. No, it doesn't currently work (well) on Win32, and there are still some rough edges (forking and killing processes is quite different on Unix compared to Windows), and no output (as wavbreaker currently only supports OSS and ALSA, although I'm working on getting PulseAudio support into it, so we could have a chance of using wavbreaker on Windows via the Windows port of PulseAudio). There are a lot dependencies to resolve (GTK+2.0 and all its dependencies) and drag into your msys/mingw installation before you can start, so I won't go about describing the whole procedure - after all, wavbreaker in it's current state isn't really usable on Windows (only display and cutting works, no audio playback). Anyway, here's the obligatory proof-of-concept screenshot:

Monday, November 19, 2007

Disabling startup sound/chime on the MacBook

Today at university, a fellow student asked me about how I disabled the startup chime/sound that the MacBook makes when it is powered on from cold state. I remembered I applied some setting after a suggestion on the mactel-linux-users mailing list, but I didn't remember exactly how I did it. Just in case, I need to repeat this procedure, and to tell him what worked for me, I started looking for the corresponding post. Here it is: how to silence apple startup chime.

Good thing that OS X is based on BSD, and therefore very unix-y, we can simply edit the local shutdown script (/etc/rc.shutdown.local) and append the following line:
/usr/sbin/nvram SystemAudioVolume=%80
This will set the volume in nvram to zero and effectively disable the startup chime, so you won't be annoyed by the startup chime when you forgot to mute the OS X audio volume before shutdown. The good thing with this method is that you don't need to install nasty third-party software, and that it still preserves the volume settings inside Mac OS X and (of course) in Linux, thanks to alsactl's restore functionality.

Friday, November 16, 2007

Patch for Jilorio

Alberto Ruiz has posted a nice little utility on his blog in July. I've tried this script several weeks ago, and found some problems (deprecated gtk calls, about box annoyances, default icon) that I quickly fixed in my local git clone. I haven't used Jilorio since, but the patch still works, so if there are still Jilorio users out there, you might want to start from the upstream git repository and apply my patch on top of this codebase.

Thursday, November 8, 2007

Episode selector dialog for gPodder

Today after University, I decided to hack a feature into gPodder that I have thought about for a while - the episode selector dialog. It should be used in several user interaction situations where a simple binary question is not specific enough ("delete old episodes?" vs "which of these old episodes do you really want to remove?"). So I set out implementing this neat little feature and when I looked at the watch and decided that I had to leave for math classes, most of the episodes selector has been implemented, with quite some fancy features and options. I used the last two hours to look through the my working copy diff to fix some obvious omissions, but as of now, the code of the new episode selector is already in SVN. I've attached some screenshots so you can see how it looks.

Thanks to lambda expressions, PyGTK coolness and getattr, i.e. accessing attributes by name, this dialog is now quite customizable and the code is still readable and (compared to what other languages would have yielded), small. If you are using gPodder, be sure to check out the current SVN trunk head.

One feature I used several times was enumerate() - you give an iterable as parameter, and get a generator that yields tuples with two elements - a zero-based index and the values you would normally get from the iterables directly. So, instead of writing code like this:
index = 0
for item in items:
print 'item %d is %s' % ( index, item )
index += 1
you can simply write
for index, item in enumerate( items):
print 'item %d is %s' % ( index, item )
which isn't only nicer, but you save two lines and the code is IMHO more readable (you instantly recognize "index" as being related to the for loop in the second code snippet).

Saturday, November 3, 2007

Massive mail and web hosting in Debian

I migrated some web and mail services from a custom Linux distro with Apache2 and Cyrus-imapd to Apache2.2 and Dovecot (imapd + pop3d). Because there are lots of Domains, Subdomains and mail aliases, I wanted to unify as much of the configuration as possible to make maintaining the services easier.

Massive name-based virtual hosting with Apache2

The document "Dynamically configured mass virtual hosting" in the Apache HTTP Server documentation describes how to set up dynamic virtual hosting. I needed name-based virtual hosting, so I created a file "/etc/apache2/conf.d/vhosting" with the following contents:

UseCanonicalName Off
VirtualDocumentRoot /srv/www/%-2.0+.%-1/%-3+/

AllowOverride all
Options +Indexes

This will automatically map subdomain.example.com to /srv/www/example.com/subdomain/. You can then even think of more sophisticated usage, such as placing a .htaccess file with a Redirect directive in /srv/www/redirected-domain.tld/.

Migrating Cyrus mails to Dovecot Maildirs

Fazal Majid has written a Python script that can be found in this blog post. You might have to modify a bit, but apart from that, it serves the purpose well. After you have converted the (nonstandard) Cyrus mail dir to the standard Maildir(++) format, the Maildirs can be used with the Dovecot mail server. Of course, you should configure exim4 to deliver new mail into "Maildir" in the users' home directories.

Massive E-Mail virtual hosting with Exim4

Another problem that arose was multiple domains and different users for E-Mail. Thankfully, Aron HÃ¥kanson has had the same problem and written the article Virtual domains with Exim 4, in which he describes how to set up massive E-Mail virtual hosting on Debian with Exim4. This makes maintaining a plaintext list of mail alias mappings for virtual servers and a list of domains for which to handle mails very easy and keeps the list maintainer happy.