Thursday, December 28, 2006

No H.264 playback on Sony Ericsson W850?

My new gadget, the Sony Ericsson W850, is able to play back video (in addition to being able to record video, take photos, play music, and only incidentally, to make phone calls). It has a 320x240 screen (same as gen-5 iPod), and according to its freely available tech specs, supports "MPEG-4 Simple Visual Profile Level 0, H.263, H.264 Baseline Profile Level 1". My experience though is that it can't play back H.264, at least it didn't play back anything I could produce. I tried both encoding a few minutes clip from a DVD using Handbrake, as well as converting another few minutes DivX clip using iSquint, and the results are the same with both: I tried every combination of settings in both programs, and the combinations where vanilla MPEG-4 is used result in a video file that plays okay on the phone, and the combinations where H.264 is used result in a video file that results in a black screen on the phone (although the audio plays okay).

I have to stress that I'm not saying the device doesn't play H.264. I'm just saying that several video files converted by the above two programs with H.264 option selected didn't play. I could've run into some profile capability violation or something similar - I'm not that much knowledgeable in video encoding. Some people say I should try experimenting with command line ffmpeg. Honestly, I won't. It's not that important, really. While I can find time to listen to music on the go, I really can't imagine I'll want to watch any video content squinting at the 2" screen. The ammount of time I decided to invest in this went only so far as to try comfortable GUI options, with motivation being "because it was there." If anyone has more success than me though, please let me know.

Wednesday, December 27, 2006

Another kludge in Java - varargs

Varargs in Java. Seriously, who needed this?

You're probably aware of my position on Java Generics, how I view their implementation to be a horrific kludge, a compromise made in name of backward compatibility where the backward compatibility issues are in fact nonexistent.

Now, here's a new discovery - vararg methods. Someone asked on the Rhino list whether we can support them, and I answered that as long as he passes the vararg argument explicitly as an array, then yes. I decided to investigate the problem further within a codebase I'm truly familiar with - FreeMarker's BeansWrapper. I quite quickly came up with a scheme for supporting non-overloaded vararg methods. However, for overloaded ones, the exercise becomes, shall we say, a bit more involved. As I had to discover, the overloaded method resolution algorithm from Java Language Specification (JLS) 2nd edition was seriously overwritten into a three-stage algorithm in JLS 3rd edition, of which the "old" (mathematically quite elegant) algorithm from JLS 2 became the second stage. I probably need some additional time to grasp it, but it looks quite horrible now. If you wish, compare:

"Method Invocation Expressions" section in JLS 2 

with

"Method Invocation Expressions" section in JLS 3.

Of course, the chapters regarding type conversions (required, as overloaded method resolution relies on the definition of "method invocation conversions", a subset of conversions that is allowed between actual and declared parameter types when invoking a method) are also substantially rewritten to cope with boxing, unboxing, and generic types.

And the worst part? Varargs are yet another Java the Language feature implemented without a Java the Virtual Machine support. They're purely syntactic sugar, with vararg argument being an array on bytecode level. Several annoying things:

  1. reflection is unaware of it. You can't just pass more arguments to the method, you have to pass the vararags arguments in an explicitly allocated array.
  2. No automatic object-to-primitive conversion when using reflection. If the vararg method's type is "int...", you must pass int[], not an Integer[]. Compare this with automatic 
    conversion for regular argument types.
  3. Unintuitive behaviour. Quick, should the following example print 1 or 0:
public class Test {
  static void x(Object... i) {
    System.out.println(i.length);
  }
  public static void main(String[] args) {
    x(new Object[0]);
  }
}

Transparent Desktop Trick

Take a photo of what's behind your computer screen, and set it as your desktop wallpaper. With little care, the results are amazing. See it here.

Labels

So, Blogger got out of beta, and finally it added a labelling feature, which is something I wished for for quite a long time. I decided to label my post to sort them into categories. The categories are (in decreasing order of number of posts at the moment):

software for anything related to software development in general. Java, Open Source, concurrency, programming languages theory. Stuff you'd want to read if you're a fellow software developer.
side interests for serious stuff that I'm interested in as an amateur. Quantum mechanics, astronomy, math, society, politics etc.
mac is for stuff you don't care to read if you aren't interested in Apple computers.
personal is for writings of personal nature.
fun is for art/entertainment/humour things I came across and want to share them with you.
blog a very low volume, blog-related announcements (like this post).

I tried to keep the number of categories to a reasonable minimum, trying to partition the content into as few of them as possible, taking into account possible reasons people read the blog (i.e. it's different for those who track what I do in the software industry, and again different for friends and family).

The links above have associated RSS feeds, so you can choose to syndicate in your reader only those categories you care about. This will probably cause less frustration for me in the future as well, as sometimes I was reluctant to post a more personal writing because I didn't want to decrease the signal-to-noise ratio for (I presume) majority of people who only care for my software-related posts. Heck, I might even post some personal writings in Hungarian now :-)

Friday, December 15, 2006

MacHeist

Via Lifehacker:

MacHeist Bundle is a bundle of 10* highly popular Mac shareware applications. This week only (which means for the next 2 days and 18 hours now), you can purchase them in a bundle for $49 instead of their combined list price of 308$.

Additionaly, 25% of your purchase goes to charity.

What are you waiting for?

*To be completely honest, it's 9 apps at the moment. 10th app is TextMate, and it'll get unlocked (meaning a license code will be sent to everyone who purchased the bundle) if the total raised for charity reaches $100k. It's currently at $67k, so there's realistic chance to get TextMate too as part of the bundle.

Tuesday, December 12, 2006

AAC is better than MP3, Walkman instead of iPod, and what Think Different means to me

Fun fact I learned today: AAC encoding sounds better than MP3 at the same bitrate. Seen here. Re-ripping my CDs right now.

I also bought myself a new cellphone, a Sony Ericsson W850i, and despite some concerns I had initially, the gadget is just brilliant. It has a very decent digital music player built-in (Sony markets them under its Walkman brand) and comes with a 1GB memory stick (I can plug in a bigger one, up to 4GB, and am actively considering buying one), and I can just throw music files from my iTunes library to it using Mac OS X built-in Bluetooth File Exchange app, and it'll nicely index them and add them to its own library. Plays both MP3 and AAC, and recognizes Apple's proprietary iTunes metadata. Just sweet. Guess I'll defer buying myself an iPod for now. Kriszti and me are going on a longish trip to Graz for New Year, so we'll see how it holds up against prolonged use, battery life and overall experience-wise. The phone's contact list and calendar are also syncable with Mac's Address Book and iCal using iSync (after buying a plugin online for 1.43 GBP), a critical feature for me.

As a matter of fact, I initially bought a Samsung Z560, since it's the only phone on the continent at the moment offering HSDPA (think GPRS, only at 1.5MB/s!), but had to return it to T-Mobile after an hour of use and a short frantic search on discussions.apple.com after I realized that it can't sync with Mac, and is not likely it ever will. (Why? Because apparently Samsung has several divisions producing cellphones, 
and each of them uses a different sync protocol, and all of them are proprietary...)

And this brings me to the point of that I'm slowly learning what the Apple slogan "Think Different" might mean to me. It means "shake off your Windows-user assumption that any periferial device will work with your computer". I bought a laser printer earlier this year that only works with Mac after installing some cross-compiled Linux drivers. I bought a cellphone that doesn't sync with Mac (fortunately could exchange it for another). I've learned the lesson. I'm shopping for a joystick now, but am not even looking at anything that doesn't feature "Mac compatible" on the box. There's simply no such thing as "maybe it'll work". It's either "it is supported and then Just Works(tm)", or it is "don't even try". In very rare circumstances you can find stuff that is not supported, but works with more or less effort, but it is really a question of dumb luck. Like Sony Ericsson W850i (with a 3rd party plugin - although to be perfectly honest, Apple supports all Sony Ericsson phones, W850i is just too new, and next release of iSync will probably support it out of box), or my Xerox laser printer (works if you dare install a cross-compiled inux CUPS driver). Think Different = Don't Assume It'll Work. Get Used To Doing More Research Than When You Used Windows.

Wednesday, December 06, 2006

Dungeon Master miscellanea

My 16-17 year old self has spent more time playing Chaos Strikes Back on Atari ST than my 32-year old self dares to admit.

Turns out, there's a whole fan subculture for Dungeon Master and Chaos Strikes Back out there. There's The Dungeon Master & Chaos Strikes Back Encyclopaedia with information about games as well as a download section with several reincarnations of the games.

Most notable among them is one by one Paul R. Stevens who created an exact replication of the game. Here's how he did it, in his own words found here:


Finally, after many years, I got my hands on the binary executable for the game. I wrote a disassembler to turn it into human-readable op-codes and proceeded to translate it to C++ using the Microsoft Version 6.0 C++ compiler. Eight hours a day for six months. About 120,000 lines of pseudo-assembly language. Crazy thing to do. But it works.

Just insane. Clearly, one of the highest examples of computer nerdiness I've ever came across. Hat off. The biggest achievement is that the resulting code is fairly cross-platform; there are distributions for Windows, Linux, and Mac OS X. And I can certify, the gameplay feeling is identical to that you get from playing it on an original Atari ST. Well, except it loads much faster. And the pixels look blockier on these damned modern high-res displays than they did on a TV screen back in the day. And the Mac OS X port for some reason doesn't deal well with keymaps, so you lose the ability to strafe from the keyboard, which can make the game tedious at times. The Windows version fares better in this regard, and you can even assign mouse clicks on a particular screen coordinate to keys on the keyboard. As anyone who played these games in original will attest, this is an invaluable feature to have as it is much faster to hit 6,4,4,spacebar than to click on four icons on the screen to cast a fireball :-)

Then there's Dungeon Master Java by Alan Berfield, an also cross-platform version of Dungeon Master engine written in Java, with custom raytraced art, giving the game a bit more polished feel.

And then if you look a bit more around on the net with a search engine, you can also find an incredible ammount of custom-designed dungeons fans are creating.

Jeez, now if only I again had as much time as I had 16 years ago...

Saturday, December 02, 2006

Poor Man's Message Prioritization

Imagine that you have a distributed enterprise system held together with messaging middleware (JMS, to be specific). Imagine that it's processing a steady load of work in bulk, but not too often there is some time sensitive operation and your system needs to expedite a message or two to meet its time constraints.

If you're lucky, your chosen JMS provider supports message prioritization. Turns out that unfortunately many do not - they simply ignore the priority parameter in MessageProducer.send(). The one I happen to be using also does not support prioritization. Switching to a different provider turned out not to be an option unfortunately - after spending a nontrivial ammount of time (about a month) testing few other, both open source and commercial offerings, none had both the performance and high-availability of the one we originally used.

What I did to overcome the lack of prioritization was "inventing" (quote marks as quite possibly other people had the same idea already) what I'm referring to as "poor man's message prioritization" - instead of using a queue FOO, I now use two queues FOO and FOO_H (for "H"igh priority) and split the JMS sessions used to process the FOO queue into two separate sets of dedicated processors for FOO and FOO_H, typically with only few sessions servicing the "_H" queue, i.e. a 95%/5% split.

What's important to realize is that what's implemented here ain't a message prioritization. It's just separation of traffic. Logically, the queues FOO and FOO_H are treated from the system's point of view as a single queue, and I refer to the individual "physical" queues as "lanes". Sometimes I refer to this technique as "laned JMS".

It does however create the illusion of prioritization as long as the ratio of prioritized traffic to nonprioritized traffic is lower than the ratio of threads processing prioritized traffic to threads processing nonprioritized traffic. It's a workaround for an annoying lack of a feature in the JMS provider. I won't pretend I'm happy with this - it works, and the implementation I came up turned out to be quite clean, but it's still more work to do for me and more complexity in my code; it should've been taken off my back by the JMS provider vendor.

As for technical implementation, it might sound tedious to implement this across the whole codebase, but is actually not that awful:


  • On the message producing side, it's sufficient to write a wrapper implementation of JMS Connection interface that is mostly pass-through, except it creates wrapper Sessions, that are themselves mostly pass-through, except they create wrapper MessageProducers, that are again mostly pass-through, but implement the send method with a priority parameter so that if priority is less than 6, the message goes to the base queue, otherwise to the "_H" queue. This way, client code that sends messages just keeps using the Connection.createSession(), Session.createProducer(), and MessageProducer.send() API with priority parameters and is just blissfully unaware of laning in the background.

  • On the message consuming side, it'd be tricky to implement this across the board, but luckily all my JMS based message consumer services build on a common codebase that I modelled after the Servlet container/Servlet API model - basically, I have a "JmsServiceContainer" (analogous to Servlet container) that deals with session management and other JMS plumbing, and a "JmsService" interface (analogous to the Servlet interface) whose implementations are more-or-less factories for session-specific MessageListeners that do the actual work on a single message. So, I only had to write the enabling code for laned processing in the "JmsServiceContainer" - basically assign the same JmsService to both lanes of a queue. This way, the "JmsService" implementations also remain blissfully unaware - they're just creating message listeners, and don't care that the messages for those listeners now come from two different queues.

Business trip DTD


<!ELEMENT business-trip (
airport,
(office,drink?,dinner,drink+,shower,sleep,breakfast?)+,
airport
)>

There were efforts to somehow fit a new element, sightseeing into a revised specification, and specify it in the business-trip's content with an optional quantifier, however usability research has shown that real-world documents would almost never contain an instance of it, mainly due to external forces that work to keep the document size at minimum.