More iPod fun

Last time I explained how to get .OGG-feeds to your iPod.

Today I’ll show you one possible direction one could go to greatly increase the usability of non-official (read: not bought at audible.com) audiobooks you may have lying around in .MP3 format.

You see, your iPod threats every MP3-File of your library as music, regardless of length and content. This can be annoying as the iPod (rightly so) forgets the position in the file when you stop playback. So if you return to the file, you’ll have to start from the beginning and seek through the file.

This is a real pain in case of longer audiobooks and / or radio plays of which I have a ton

One way is to convert your audiobooks to AAC and rename the file to .m4b which will convince iTunes to internally tag the files as audiobooks and then enable the additional features (storing the position and providing UI to change play speed).

Of course this would have meant converting a considerable part of my MP3 library to the AAC-format which is not yet as widely deployed (not to speak of the quality-loss I’d have to endure when converting a lossy format into another lossy format).

It dawned me that there’s another way to make the iPod store the position – even with MP3-files: Podcasts.

So the idea was to create a script that reads my MP3-Library and outputs RSS to make iTunes think it’s working with a Podcast.

And thus, audiobook2cast.php was born.

The script is very much tailored to my directory structure and probably won’t work at your end, but I hope it’ll provide you with something to work with.

In the script, I can only point out two interesting points:

  • When checking a podcast, iTunes ignores the type-attribute of the enclosure when determining whether a file can be played or not. So I had to add the fake .mp3-extension.
  • I’m outputting a totally fake pubDate-Element in the <item>-Tag to force iTunes to sort the audiobooks in ascending order.

As I said: This is probably not useful to you out-of-the-box, but it’s certainly an interesting solution to an interesting problem.

Updating or replacing datasets

This is maybe the most obvious trick in the world but I see people not doing it all over the place, so I guess it’s time to write about it.

Let’s say you have a certain set of data you need to enter into your RDBMS. Let’s further assume that you don’t know whether the data is already there or not, so you don’t know whether to use INSERT or UPDATE

Some databases provide us with something like REPLACE or “INSERT OR REPLACE”, but others do not. Now the question is, how to do this efficiently?

What I always see is something like this (pseudo-code):

  1. select count(*) from xxx where primary_key = xxx
  2. if (count > 0) update; else insert;

This means that for every dataset you will have to do two queries. This can be reduced to only one query in some cases by using this little trick:

  1. update xxx set yyy where primary_key = xxx
  2. if (affected_rows(query) == 0) insert;

This method just goes ahead with the update, assuming that data is already there (which usually is the right assumption anyways). Then it checks if an update has been made. If not, it goes ahead and inserts the data set.

This means that in cases where the data is already there in the database, you can reduce the work on the database to one single query.

Additionally, doing a SELECT and then an UPDATE essentially does the select twice as the update will cause the database to select the rows to update anyways. Depending on your optimizer and/or query cache, this can be optimized away of course, but there are no guarantees.

Careful when clean-installing TabletPCs

At work, I got my hands on a LS-800 TabletPC by motion computing and after spending a lot of time with it and as I’m very interested in TabletPCs anyways, I finally got myself its bigger brother, the LE-1700

The device is a joy to work with: Relatively small and light, one big display and generally nice to handle.

The tablet came with Windows XP preinstalled and naturally, I wanted to have a look at the new Tablet-centric features in Vista, so I went ahead and upgraded.

Or better: Clean-installed.

The initial XP installation was german and I was installing an english copy of Vista which makes the clean installation mandatory.

The LE-1700 is one of the few devices without official Vista-support, but I guess that’s because of the missing software for the integrated UMTS modem – for all other devices, drivers either come prebundled with Vista, are available on Windows update or you can use the XP drivers provided at the Motion computing support site.

After the clean installation, I noticed that the calibration of the pen was a bit off – depending on the position on the screen, the tablet noticed the pen up to 5mm left or above the actual position of the pen. Unfortunately, using the calibration utility in the control panel didn’t seem to help much.

After some googling, I found out what’s going on:

The end-user accessible calibration tool only calibrates the screen for the tilt of the pen relative to the current position. The calibration of the pens position is done by the device manufacturer and there is no tool available for end-users to do that.

Which, by the way, is understandable considering how the miscalibration showed itself: To the middle of the screen it was perfect and near the sides it got worse and worse. This means that a tool would have to present quite a lot of points for you to hit to actually get a accurately working calibration.

Of course, this was a problem for me – especially when I tried out journal and had to notice that the error was bad enough to take all the fun out of hand-writing (imagine writing on a paper and the text appearing .5cm left of where you put the pen).

I needed to get the calibration data and I needed to put it back after the clean installation.

It turns out that the linear calibration data is stored in the registry under HKLMSYSTEMCurrentControlSetControlTabletPCLinearityData in the form of a (large) binary blob.

Unfortunately, Motion does not provide a tool or even reg-file to quickly re-add the data should you clean-install your device, so I had to do the unthinkable (I probably could have called support, but my method had the side effect of not making me wait forever for a fix):

I restored the device to the factory state (by using the preinstalled Acronis True Image residing on a hidden partition), exported the registry settings, reinstalled Vista (at which time the calibration error resurfaced), imported the .reg-File and rebooted.

This solved the problem – the calibration was as smooth as ever.

Now, I’m not sure if the calibration data is valid for the whole series or even defined per device, but here is my calibration data in case you have the same problem as I had.

If the settings are per device or you have a non-LE-1700, I strongly advise you to export that registry key before clean-installing

Obviously I would have loved to know this beforehand, but… oh well.

PHP, stream filters, bzip2.compress

Maybe you remember that, more than a year ago, I had an interesting problem with stream filters.

The general idea is that I want to output bz2-compressed data to the client as the output is being assembled – or, more to the point: The PopScan Windows-Client supports the transmission of bzip2 encoded data which gets really interesting as the amount of data to be transferred increases.

Even more so: The transmitted data is in XML format which is very easily compressed – especially with bzip2.

Once you begin to transmit multiple megabytes of uncompressed XML-data, you begin to see the sense in jumping through a hoop or two to decrease the time needed to transmit the data.

On the receiving end, I have an elaborate construct capable of downloading, decompressing, parsing and storing data as it arrives over the network.

On the sending end though, I have been less lucky: Because of that problem I had, I was unable to stream out bzip2 compressed data as it was generated – the end of the file was sometimes missing. This is why I’m using ob_start() to gather all the output and then compress it with bzcompress() to send it out.

Of course this means that all the data must be assembled before it can be compressed and the sent to the client.

As we have more and more data to transmit, the client must wait longer and longer before the data begins to reach it.

And then comes the moment when the client times out.

So I finally really had to fix the problem. I could not believe that I was unable to compress and stream out data on the fly.

It turns out that I finally found the smallest possible amount of code to illustrate the problem in a non-hacky way:

So: This fails under PHP up until 5.2.3:

<?
$str = "BEGIN (%d)n
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
nEND (%d)n";

$h = fopen($_SERVER['argv'][1], 'w');
$f = stream_filter_append($h, "bzip2.compress", STREAM_FILTER_WRITE);
for($x=0; $x < 10000; $x++){
   fprintf($h, $str, $x, $x);

}
fclose($h);
echo "Writtenn";
?>

Even worse though: It doesn’t fail with a message, but it writes out a corrupt bzip-File.

And it gets worse: With a little amount of data it works, but as the amount of data increases, it begins to fail – at different places depending on how you shuffle the data around.

Above script will write a bzip file which – when uncompressed – will end around iteration 9600.

So now that I had a small reproducible testcase, I could report a bug in PHP: Bug 47117.

After spending so many hours on a problem which in the end boiled down to a bug in PHP (I’ve looked anywhere, believe me. I also tried workarounds, but all to no avail), I just could not let the story end there.

Some investigation quickly turned up a wrong check for a return value in bz2_filter.c which I was able to patch up very, very quickly, so if you visit that bug above, you will find a patch correcting the problem.

Then, when I finished patching PHP itself, hacking up the needed PHP-code to let the thing stream out the compressed data as it arrived was easy. If you want, you can have a look at bzcomp.phps which demonstrates how to plug the compression into either the output buffer handling or something quick, dirty and easier else.

Oh, and if you are tempted to do this:

function ob($buf){
        return bzcompress($buf);
}

ob_start('ob');

… it won’t do any good because you will still gobble up all the data before compressing. And this:

function ob($buf){
        return bzcompress($buf);
}

ob_start('ob', 32768);

will encode in chunks (good), but it will write a bzip2-end-of-stream marker after every chunk (bad), so neither will work.

Nothing more satisfying than to fix a bug in someone else’s code. Now let’s hope this gets applied to PHP itself so I don’t have to manually patch my installations.

Upscaling video

I have an awesome Full-HD projector and I have a lot of non-HD video material, ranging from DVD-rips to speedruns of older consoles and I’m using a Mac Mini running Windows (first Vista RC2, then XP and now Vista again) connected to said projector to access the material.

The question was: How do I get the best picture quality out of this setup.

The answer boils down to the question of what device should do the scaling of the picture:

Without any configuration work, the video is scaled by your graphics card which usually does quite a bad job at it unless it provides some special upscaling support which the intel chip in my Mac Mini seems not to.

Then you could let the projector do the scaling which would require the MCE application to change the screen resolution to the resolution of the file played. It would also mean that the projector has to support the different resolutions the files are stored in which is hardly the case as there are some very strange resolutions here and then (think game boy’s native 140×102 resolution).

The last option is to let your CPU do the scaling – at least to some degree.

This is a very interesting option, especially as my Mac Mini comes with one of these nice dual core CPUs we can try and leverage for this task. Then, there are a lot of algorithms out there that are made exactly for the purpose of scaling video, some of which are very expensive to implement in specialized hardware like GPUs or the firmware of a projector.

So I went around and finally found this post outlining the steps needed to configure ffdshow to do its thing.

I used the basic setting and modified it just a bit to keep the original aspect ratio of the source material and to only do the resizing up to the resolution of 1280×720. If the source is larger than this, there’s no need to shrink the video just to use the graphics chip to upscale it again to the projectors native 1920×1280 resolution (*sigh*).

Also, I didn’t want ffdshow to upscale 1280×720 to the full 1920×1280. At first I tried that, but I failed to see a difference in picture quality, but I had the odd frame drop here and then, so I’m running at the limits of my current setup.

Finally, I compared the picture quality of a Columbo (non-referal link to Amazon – the package arrived last week) DVD rip with and without the resizing enabled.

The difference in quality is immense. The software-enhanced picture looks nearly like a real 720p movie – sure: Some details are washed-up, but the overall quality is worlds better than what I got with plain ffdshow and no scaling.

Sure. The CPU usage is quite a bit higher than before, but that’s what the CPUs are for – to be used.

I highly recommend you taking the 10 minutes needed to set up the ffdshow video decoder to do the scaling. Sure: The UI is awful and I didn’t completely understand many of the settings, but the increased quality more than made up the work it took to configure the thing.

Heck! Even the 240×160 pixel sized Pokémon Sapphire run looked much better after going through ffdshow with software scaling enabled.

Highly recommended!

By the way: This only works in MCE for video files as MCE refuses to use ffdshow for MPEG2 decoding which is needed for DVD or TV playback. But 100% of the video I watch are video files anyways, so this doesn’t bother me at all.

Altering the terminal title bar in Mac OS X

After one year of owning a MacBook Pro, I finally got around to fix my precmd() ZSH-hack to really make the current directory and stuff appear in the title bar of Terminal.app and iTerm.app.

This is the code to add to your .zshrc:

case $TERM in
    *xterm*|ansi)
		function settab { print -Pn "e]1;%n@%m: %~a" }
		function settitle { print -Pn "e]2;%n@%m: %~a" }
		function chpwd { settab;settitle }
		settab;settitle
        ;;
esac

settab sets the tab contents in iTerm and settitle does the same thing for the title bar both in Terminal.app and iTerm.

The sample also shows the variables ZSH replaces in the strings (the parameter -P to print lets ZSH do prompt expansion. See zshmisc(1) for a list of all variables): %n is the currently logged on user, %m the hostname up until the first dot and %~ is displaying the current directory or ~ if you are in $HOME. You can certainly add any other environment variable of your choice if you need more options, but this more or less does it for me.

Usually, the guides in the internet make you use precmd to set the title bar, but somehow, Terminal wasn’t pleased with that method and constantly kept overwriting the title with the default string.

And this is how it looks in both iTerm (above) and Terminal (below):

PT-AE1000 HDMI woes

Today was the day when I got the crown jewel of my home entertainment system: A Panasonic PT-AE1000

The device is capable of displaying the 1920×1080 resolution which means that it’s capable of showing 1080p content (at 50,60 and even 24 Hertz). It’s the thing that was needed to complete my home entertainment setup.

The projector is quite large but not that heavy. I also like the motorized lens controls for zoom and focus and I love the incredible lens shift range: You can basically move the picture the whole size of it in any direction. This allowed me not to tilt the device even though it’s mounted quite high up on the ceiling. No tilt means no keystone distortion.

Even though all projectors provide you with some means to correct the keystone effect, but you’ll automatically lose picture quality and content when using it, so it’s best to leave it off.

Unfortunately, the device has one flaw: It reports totally wrong screen resolutions via DCC when you connect the projector via DVI (or HDMI, but that’s the same thing).

It tells windows (strangely enough, it works on Mac OS X) that it supports the resolution of 1920×540 at some strange refresh rate of around 54 Hz.

The intel chipset of my Mac Mini can’t output this resolution so it falls back to 480p and there’s no possiblity of changing this.

With the help of PowerStrip (which you won’t even need when you are reading this), I created a corrected Monitor .INF-File that has the correct resolution and acceptable refresh rates in it (taken from the projectors manual).

Once you tell windows to update the driver of your monitor and point it to this file specifically, it will allow you to set the correct resolution.

*phew* – problem solved.

Aside of this glitch, so far, I love the projector. Very silent, very nice picture quality, perfect colors and it even looks quite acceptable with its black casing. This is the projector I’m going to keep for many years as there’s no increase of resolution in sight for a very long time.

The return of Expect: 100-continue

Yesterday I had to work with a PHP-application using the CURL library to send a HTTP POST request to a lighttpd server.

Strangely enough I seemed unable to get anything back from the server when using PHP and I got the correct answer when I was using wget as a reference.

This made me check the lightpd log and I once more (I recommend you to read that entry as this is very much dependent on it) came across the friendly error 417

A quick check with Wireshark confirmed: curl was sending the Expect: 100-continue header.

Personally, I think that 100-continue thing is a good thing and it even seems to me that the curl library is intelligent about it and only does that thing when the size of the data to send is larger than a certain threshold.

Also, even though people are complaining about it, I think lighttpd does the right thing. The expect-header is mandatory and if lighttpd doesn’t support this particular header, the error 417 is the only viable option.

What I think though is that the libraries should detect that automatically.

This is because they are creating a behavior that’s not consistent to the other types of request: GET, DELETE and HEAD requests all follow a fire-and-forget paradigm and the libraries employ a 1:1 mapping: Set up the request. Send it. Return the received data.

With POST (and maybe PUT), the library changes that paradigm and in fact sends two request to the wire while actually pretending in the interface that it’s only sending one request.

If it does that, then it should at least be capable enough to handle the cases where their scheme of transparently changing semantics breaks.

Anyways: The fix for the curl-library in PHP is:

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

Though I’m not sure how pure this solution is.

Vista, AC3, S/PDIF

Since around December 31th last year, my home cinema is up and running. That day was the day when I finally had all the equipment needed to mount the screen that has arrived on December 29th.

It was a lot of work, but the installation just rocks. And I’ve already blogged about the main components of the thing: The Gefen HDMI extender and the Denon AVR-4306.

The heart of the system consists of shion serving content (thankfully, the TB harddrive was announced last week – it’s about time) and a brand new 1.8Ghz Mac Mini running Windows Vista (RC2) in BootCamp which is actually displaying the content.

I’ve connected a windows media center remote receiver which Microsoft sells to OEMs to use the old IR remote of my Shuttle MCE machine.

The mac mini is connected to the Denon receiver via a DVI to HDMI adaptor and optical digital cable for the audio.

And that last thing is what I’m talking about now.

The problem is that Microsoft changed a lot about how audio works in Vista and I had to learn it the hard way.

At first, I couldn’t not hear any sound at all. That’s because Vista treats all outputs of your sound card as separate entities and you can configure over which connector you want to hear which sounds.

The fix there was to set the S/PDIF connector as system default (in the sound applet of control panel) which fixed the standard windows sounds and stereo sound for me.

Actually, the properties screen of the S/PDIF connector already contains options for AC3 and DTS, complete with a nice testing feature allowing you to check your receiver’s support for the different formats by actually playing some multichannel test sound.

The problem is that this new framework is mostly unsupported by the various video codecs out there.

This means that even if you get that control panel applet to play the test sound (which is easy enough), you won’t get AC3 sound when you are playing a movie file. You still need to get a codec for that.

But most codecs don’t work right any more in vista as the S/PDIF connector now is a separate entity and seems to be accessed differently than in XP.

Usually, the only thing I install on a new windows machine I need to play video with is ffmpeg which actually has some limited support for Vista’s way of handing S/PDIF: In the audio settings dialog, you can select “Output” and then in the formats list for S/PDIF, you can check AC/3. Unfortunately, this unchecks the PCM formats.

This means that you will get sound in movies with an AC3 track, but no sound at all in every other movie – ffmpeg seems (emphasis on seems – I may just not have found a way yet) unable to either encode stereo to AC3 or output both PCM and AC3 without changing settings (not at the same time of course).

AC3filter works better in that regard.

Depending on hour of the day (…), it’s even able to work with the S/PDIF output without forcing it to encode stereo to AC3 (which AC3filter is capable to do).

So for me the solution to the whole mess was this:

  1. Install the latest build of ffmpeg, but don’t let it handle audio
  2. Install AC3filter
  3. Open the configuration tool and on the first page enable S/PDIF.
  4. On the system tab, enable passthrough for AC3 and DTS.

This did the trick for me.

As time progresses, I’m certain that the various projects will work better and better with the new functionality in Vista which will make hassles like this go away.

Until then, I’m glad I found a workable solution.

VMWare Server, chrony and slow clocks

We have quite many virtual machines running under VMWare server. Some for testing purposes, some for quite real systems serving real webpages.

It’s wonderful. Need a new server? Just cp -r the template I created. Need more RAM in your server? No problem. Just add it via the virtual machine configuration file. Move to another machine? No problem at all. Power down the virtual machine and move the file where you want it to be.

Today I noticed something strange: The clocks on the virtual machines were way slow.

One virtual second was about ten real seconds.

This was so slow that chrony which I used on the virtual machines thought that the data sent from the time servers was incorrect, so chrony was of no use.

After a bit of digging around, I learned that VMware server needs access to /dev/rtc to provide the virtual machines with an usable time signal (usable as in “not too slow”).

The host’s /var/log/messages was full of lines like this (you’ll notice that I found yet another girl from a console RPG to name that host):

Dec 15 16:12:58 rikku /dev/vmmon[6307]: /dev/rtc open failed: -16
Dec 15 16:13:08 rikku /dev/vmmon[6307]: host clock rate change request 501 -> 500

-16 means “device busy”

The fix was to stop chrony from running on the host machine so VMWare could open /dev/rtc. This made the error messages vanish and additionally it allowed the clocks of the virtual machines to work correctly.

Problem solved. Maybe it’s useful for you too.