Sunday, 31 August 2008

Test Driven Development Screencast

Today I've done a screencast on test-driven development.
Have a look at it over at ShowMeDo.

Saturday, 30 August 2008

findsilence 0.1rc3

The first release candidate of findsilence was released today.
I forgot posting the other releases to here, but this one I am. The changelog can be found at http://name.nonlogic.org/findsilence/CHANGELOG.

[Download findsilence]

Friday, 29 August 2008

Counting digits

def digits(x):
""" Return amount of digits of x. """
return int(math.floor(math.log10(x)) + 1)
Because I needed to create an efficient algorithm to count the amount of digits of a number, I have come up with the one you can read above. It is a bit slower than len(str(x)) for small numbers, but a lot faster with large ones.
Another example on how a good algorithm beats processing power.

Python mathmodule.c patch

Today I have written a patch for Modules/mathmodule.c of Python 2.6. It removes the inaccuracy of math.log when called with base 10 compared to math.log10. All it does is internally using log10 when log gets 10 as base. It makes the output of math.log much more accurate when used with base 10.
Here is some comparison:
[Unpatched Python] [Patched Python]

I hope the patch is good enough to meet Pythons high standards.
Props go out to Gromit @ freenode for helping me create the patch.

[Python Bug Tracker Issue]

Thursday, 28 August 2008

How not to do CLI

Having concerned myself with audio programming, I found out that some very established tools have a horrible command-line interface. Particularly I am talking about lame here.
It is impossible to just convert multiple files without writing a shell-script. I think that every CLI should give the user the option to use their shells' globbing features. Lame also does a good job at overriding options that users are used to them performing in a different way.
When you see lame -h, would you expect that the -h flag shows you a help, or that it increases the quality of your output file?
Or whats better to read: lame *.wav or for i in *.wav; do lame $i; done? I'd certainly answer Of course that should show me the help! and "lame *.wav" is much more concise! to these questions. And it's not that it would be that hard, at least not with Python and optparse. You just need to iterate over the input files and you are done. for arg in args: [your code here]. That's it. So with Python there is absolutely no excuse not to support multiple input files.
I think that CLI need to be thought about and designed just as much as GUI need to. They need to be powerful yet intuitive to use, and I think lame failed at being either of that. At least with Python, there's no excuse not doing it.

With findsilence I tried to achieve that. It works with just one argument, the input file(s), and it puts the output in the directory output/ in the working directory, if it is not specified using the -o flag. When it gets more than one file, it automatically puts the output of each of them into a separate directory in the output directory, if it only gets one file, it just puts the output into the output directory.
So summarizing I think there are a few things you should note when creating CLI:
  • Never change behaviour of often used options such as -h, -v, -q
  • Always accept multiple input files unless you have a good reason not to
  • Try to minimize the options that are required by keeping sane defaults for unspecified options.
  • When you have a GUI and a CLI, think about adding a flag to the CLI to start the GUI to not require the user to remember two commands.

Tuesday, 26 August 2008

findsilence release coming

I am about to release findsilence 0.1rc1. I have tweaked the values according to three different records, and am just digitizing an old Beatles record for the final test, if that works, I will release.

findsilence improved

Findsilence, that's the name I gave to my WAV splitting project, has been heavily improved in the last two days since I came back from my vacation.
I have implemented a new algorithm that should find silence more reliably than the old one, and have really improved the user interface. You now see a progressbar while the program is working, get the chance to cancel the progress if you want, and most importantly, it doesn't hang once you've started the progress.

Monday, 25 August 2008

Photograph

This is one of the photographs I took while I was in Switzerland.
I think it is the best one, and that's why I am posting it now. More may follow.

img_9047

Back Home

Today at about 7AM I arrived home at Vienna again. I will sort out the pictures now, maybe will upload the best to Flickr or a similar service.

Tuesday, 12 August 2008

Holidays

Today in the evening, I am going to leave towards Switzerland, where I'll arrive tomorrow to spend my holidays. I will return on Monday the 25th of August.
I may have WLAN access somewhere and maybe will post to here when the weather outside is not nice.

New MP3 Player

Today, as I am leaving for holidays tomorrow, I bought a new MP3 player. As buying hardware that works with Linux is like lottery, I just picked the one I liked best without even considering how it might work with Linux.
But today, I've won the Linux-Lottery. The MP3 player is fully usable by just mounting it and transferring your music to the music folder. All that even though the package explicitly stated that the product does only work with Windows. I already transferred a lot of music onto it so I can listed to it while sitting in the train. I am pretty satisfied with it, the only shortcoming is that it is only chargeable by USB, but that is not that bad as I am taking a laptop there anyway.
The only thing that, I think, is impossible with Linux is making playlists, but as I never use that feature on mobile MP3 devices anyway, it is not that bad.

It was a Sony NWZ-A826, if you are interested in buying an MP3 player that is well-supported under Linux.

Monday, 11 August 2008

Automatic Title splitting

I have written a Python program that is capable to separate tracks in a long .wav file, as long as there is silence between them. I also supplied it with a nice, minimalistic, User-Interface.
In fact, this is the first User-Interface that I've done with wxPython that really looks the way I planned it to, that resizes properly, if odd-looking, and is, in my opinion, intuitive.
The only problem with it as of now is that the User-Interface and the real splitting code are both executed in the same Thread, thus the User-Interface gets unresponsive once you hit the "Split into Tracks" button. As this is not too hard to do, I will address it in the next time.
I might even release this to the public if anyone has a use for it, but most likely not until I come home from my vacations again.

You might be wondering why I did this program?
We got a turntable capable of directly writing the music it plays onto an USB-Stick. But unfortunately, it doesn't split it into the tracks, but rather writes one big mp3 file that contains the whole record. This is my solution to that, although it is currently unable to directly work on, or at least, convert mp3 files by itself. So for now I will have to manually convert the mp3 to wav. That will change too, but I am still searching a right library for that task. Speaking of which, for the core of this application, I am only using Python builtins, so no external dependencies, but wxPython for the UI, are required.
While coding this, nearly the whole day today, I have found out that the Python documentation on wave and audioop is pretty lacking, so I had to experiment a bit to find out good default values. I might send in some patches for this.
Screenshot

Saturday, 9 August 2008

Code Styleguide

I have been working hard today to get a new styleguide up for pypentago. It describes how the code in pypentago has too look. Despite being similar to PEP8, it also addresses some things that PEP8 does not, like cross-platform file-name operations.
The outcome pretty much pleases me, as it is much longer in detail.

I have written it because at the time of writing there are still 150 PEP8-incompatible variable, class and function-names, despite me having removed some of them in the last days.

It is written using Sphinx and I might add some other developer resources to the online documentation some time later.

If you think I have missed anything in it, feel free to either contact me via email or just leave a comment.

Code Style Guide
PS: I am aware that there is some encoding problem. I will try to resolve that some time.

Thursday, 7 August 2008

Gna! SVN repository unbearable

[ gna/pypentago/trunk ] % svn update
ssh_exchange_identification: Connection closed by remote host
svn: Connection closed unexpectedly
I have been seeing this a lot lately, and when I say a lot, I mean committing fails more often than it succeeds. I often have to wait a minute or so in order to be able to commit, which I think is much too much.
I think I am going to try to find a new home for pypentago. Not that Gna! was bad, but a repository that is down when you try to commit is just unbearable.
This may also be a chance of switching to a distributed version control system, like Git or Mercurial.
At the moment I lean more towards Git, as I think its command-set is more complete, but on the other hand Mercurial is far better when it comes to writing extensions.
The most appealing thing of Git is its rebase command which takes your changes and puts them on top of another branch. While this may be dangerous and bad when you already have your branch shared, I think it is very useful for keeping your local branches up-to-date with the master branch.

UI "Action" Bindings

Today I have refactored the pypentago User-Interface code to make use of the new action module I have written. I also make heavy use of decorators in it, even using my instance-decorator hack.

I think this is an important step to modularity and I like it much better that way.
On the downside, having used git-svn, the connection failed during the dcommit which messed up git a bit and forced me to svn rm the whole source and copy the new one to it instead.

Monday, 4 August 2008

Who Can Name the Bigger Number?

You have fifteen seconds. Using standard math notation, English words, or both, name a single whole number—not an infinity—on a blank index card. Be precise enough for any reasonable modern mathematician to determine exactly what number you’ve named, by consulting only your card and, if necessary, the published literature.
I have found an interesting article dealing with numbers so big no human can imagine them.
It also contains an excursus about Turing Machines which I found particularly interesting, because they are the basis of modern computing.

In my opinion it is well-written and understandable, even for people that are not really into maths, such as me. I really enjoyed reading it and think that I learnt a lot of new things from it.

Who Can Name the Bigger Number?

Sunday, 3 August 2008

Decorator Magic

I have been using Python decorators more in the last time, finding the extremely useful. But there are some pitfalls I have experienced.
First one is that when decorating methods, there is no way for the decorator to find out whether it is a method or a function, which is a bit complicated in some cases.
The second one, that is logical though, is that the methods that get passed to the decorator are unbound methods, thus you cannot just store them in a dictionary and execute them later.
When you know which class the method is of, it is enough to just store the name(func.__name__) and get the method in the constructor of the class using getattr(self, func_name).

So what did I need decorators for, anyway?
I was searching for a way to reorganize the network code in pypentago, and seeing all those pointless self.bind("EVENT", self.method) functions, I decided that there has to be a better way.
For me, that better way were decorators, eventually leading the the following form:
@expose("EVENT")
def method(self, evt):
pass
I think this is much more readable, as that way the code of the method and the corresponding event are not so shattered across multiple sections in the code.
During that process, I have also made great use of the partial function in the functools module. It allows you to store a function with some of the parameters passed, and the other ones left for the time it is executed.
def foo(bar, spam):
print bar, spam
baz = partial(foo, spam="Spam!")
print baz("Bar!")
This will output "Bar! Spam!". It is really useful when storing functions for execution to occur later.
I think this is pretty useful, I also have create a pretty hacky way to apply decorators to bound methods by storing both the decorator and the method associated with it and decorating it in the __init__ method.