Josef “Jeff” Sipek

Audacity UI feature

Although I’m filing this under the “rants” category, don’t get fooled. The rant is about UIs in general, with Audacity being the exception.

Here’s what happened…I was going to save the recordings of my radio show to my computer, and I noticed that the first hour recording started about 4 minutes after I took over aether. That meant that I needed to get the previous hour, and cut whatever short portion into a small file and keep it along the 3 1-hour long mp3s.

For audio editing, I tend to use Audacity. It works well, it’s rather intuitive, etc., etc. I did the cut, and I was going to export it as an mp3 (to keep the file format consistent with the other 3 hours of audio, otherwise I’d make it an ogg/vorbis). Audacity let me chose the new file name, the new format, but then when it was about to start the actual encoding, this dialog popped up:

Audacity needs libmp3lame

This is absolutely brilliant! And I mean it; I’m not being sarcastic as I usually am. Normally, one of these scenarios happens…

  • …the application gives you a “I can’t find the encoder” at start (if at all), and disables export to that file format
  • …the application gives you a “I can’t find the encoder” at the start of the encoding process, forcing you to abort the encoding, potentially closing the application, to installed the codec, and redoing whatever you did and trying to re-export
  • …the application gives you a “I can’t find the encoder” at the start of the encoding process, making you look through numerous preferences windows to find the one you care about - if it even exists
  • …the application gives you a “I can’t find the encoder” at the start of the encoding process, making you trying to figure out which environment variable (LD_LIBRARY_PATH, LD_PRELOAD, etc., etc.) will make the linker do the right thing, and make the application find the .so

All are sub-optimal. Asking the user for the path to the .so, while not the newbie-friendliest of things, is really the best thing the application could do. This way, if the .so isn’t installed, the user can install it anywhere - system wide or in one’s $HOME - and then point Audacity to it. If the .so is installed but Audacity couldn’t find it, you can manually point it in the right place.

I use Debian, so installing libmp3lame was a matter of making sure I have the Debian Multimedia source in my sources.list, and then running a quick aptitude install to get it on my disk. If you are using a less privileged distro (or if you don’t have root access to install it system-wide), you’ll have to quite possibly go to the project’s website, and grab a copy there. Audacity’s UI designers haven’t failed you there. A convenient way to go to the website to download the .so is right there.

Overall, seeing this dialog didn’t make me agitated that Audacity wants something I don’t have installed, but instead it made me write this post about something that makes sense, but people fail at doing things like this.

Guilt - Two Months Later

Quite a bit has changed in Guilt over the past two months. There have been 5 releases, as well as one release candidate (v0.19-rc1). During these releases, 71 files were changed (2210 insertions, 293 deletions) in 98 commits. There has been a number of patches I got via email:

Brandon Philips: 4
Nur Hussein: 3
Theodore Ts’o: 2
Yasushi SHOJI: 7

Brandon Philips contributed a significant portion of the documentation — currently every command has a man page! Additionally, he is trying to get Guilt picked up by Debian. So if you happen to qualify as a sponsor, do the right thing ;)

Nur Hussein contributed an uninstall script as well as fixed the patchbomb script.

As far as I know, Ted Ts’o is using Guilt to maintain his ext4 tree.

Yasushi contributed created a few patches which add several bits of quilt functionality (e.g., guilt-files, and guilt-series -v).

I have also been contacted by Peter Williams, the maintainer of gquilt (a GUI wrapper for quilt and mq, with a very similar name to guilt), if I would like to have guilt added as a backend. I checked out gquilt, and it looks really nice. I also looked at what it would take to add the backend, and it doesn’t look like that much effort, but I need to implement few bits of functionality first. If anyone wants to volunteer, let me or Peter know. :)

Funny, but sad

So, I was happily browsing around the internet, when I clicked on this one link which opened a new window in firefox. At first, I almost burst out laughing. But by the time, I made the screenshot, I was very annoyed. Here’s the screenshot:

Free software

The wording is really crappy. I, as an open source/free software supporter, don’t like this very much. (I am more of an open source than free software person.) It will confuse people that don’t know any better - just like people call GPL/BSD/etc. licensed software "freeware." Grrrr. Can’t you get it? Freeware is the crap you get for Windows. Free software and Open source refer to more than that. Maybe I should send the screenshot to RMS, and let him raise hell :)

PowerDNS Strikes Again!

I have heard that an unnamed ISP has switched their DNS servers from Bind to something much better — PowerDNS. I, personally, use PowerDNS and I have only positive things to say about it. As for the ISP’s switch, I hear that they reduced they farm of ~190 Bind servers to ~60 PowerDNS servers. Impressive no matter how you look at it! If you are about to set up a DNS server, I suggest you look at PowerDNS.

Bizarre Code

Think of this as a sequel to my post about a year ago.

The following peice of code is from Unionfs’s copyup_permission(). It is (or should be) a simple function that is supposed to copy the permissions from one inode to another. Well, I can’t help but remember this one slide from Greg Kroah-Hartman’s keynote this year at Ottawa Linux Symposium. Here’s the slide:

Linux is evolution, not intelligent design.

The quote definitely applies to copyup_permission(). It seems very clear that it “evolved” to something very odd. Anyway, I shall torment you no longer, here is the code:

static int copyup_permissions(struct super_block *sb,
                              struct dentry *old_hidden_dentry,
                              struct dentry *new_hidden_dentry)
{
        struct iattr newattrs;
        int err;

        print_entry_location();

        newattrs.ia_atime = old_hidden_dentry->d_inode->i_atime;
        newattrs.ia_mtime = old_hidden_dentry->d_inode->i_mtime;
        newattrs.ia_ctime = old_hidden_dentry->d_inode->i_ctime;
        newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
                        ATTR_ATIME_SET | ATTR_MTIME_SET;
        /* original mode of old file */
        newattrs.ia_mode = old_hidden_dentry->d_inode->i_mode;
        newattrs.ia_gid = old_hidden_dentry->d_inode->i_gid;
        newattrs.ia_uid = old_hidden_dentry->d_inode->i_uid;
        newattrs.ia_valid |= ATTR_FORCE | ATTR_GID | ATTR_UID | ATTR_MODE;
        if (newattrs.ia_valid & ATTR_MODE) {
                newattrs.ia_mode = (newattrs.ia_mode & S_IALLUGO) |                
                        (old_hidden_dentry->d_inode->i_mode & ~S_IALLUGO);
        }

        err = notify_change(new_hidden_dentry, &newattrs);

        print_exit_status(err);
        return err;
}

It was actually Seth Arnold that noticed that the condition will ALWAYS be true because ATTR_MODE is set in the line just above it. Furthermore, if one eliminates the if statement and replaces newattr.ia_mode in the assignment with what it is set to just few lines before (right after the comment) he gets:

newattrs.ia_mode = (old_hidden_dentry->d_inode->i_mode & S_IALLUGO) |
                   (old_hidden_dentry->d_inode->i_mode & ~S_IALLUGO);

If you are up to speed with bitwise operations, you’ll realize that it can be simplified to:

newattrs.ia_mode = old_hidden_dentry->d_inode->i_mode;

Brilliant!

Powered by blahgd