• The Java Media Player is back on track, and I have a Web Start Demo to prove it! The reason I haven’t blogged in a while is because I haven’t made much progress compared to the time spent. I didn’t have that many problems with making things work on the Mac, except for some window ordering problems that seems to be Mac related. But creating a version without problems that worked on both the Mac and on Windows was an exercise in mind control, Vulcan style. The process was like the old game on circus where you hit frogs with a stick. Hit one and it goes away, but another one pops up…

    The performance problem I reported in the last blog is all but gone. It’s not like the problem has been solved from Java’s side, I have just found a very narrow way around the problems. Let me explain.

    The problem was that turning a window translucent would absolutely kill performance on Windows, for reasons mentioned in the last blog. I initially made one window for all graphics but that was way too slow since it needed it to be translucent. I now have four (4!) windows and it will be at least five before I’m done.

    One window is the shadow for the main window. That window is also the main application window when you count the order and owner, strangely enough, but it had to be that way. Since the shadow should show the background though it is of course translucent. But since the graphics is almost never changed the performance isn’t that relevant.

    Both sidebar windows are now normal JDialogs, but undecorated of course. They have set the shadow window as the “owner” window since it needs to be on top of it. They don’t change size when they slide, that was too slow and jerky on the Mac, it is just the graphics in the window that slides. These are also translucent and paints their own shadow. The performance here is good enough since they don’t change too much, the number of pixels are quite small and I can have full control of the painting process and optimize it like a mad pixel pushing junkie.

    The main window is a normal window, but it is “shaped” on Windows and translucent on the Mac. This means that hardware acceleration will be in place for the main window, where it is most needed. You can see that it is a shaped window on Windows since the corners are pixelated. I do however have a sneaky way to solve this. I will paint the corners on the background shadow window instead, where we have translucency and thus anti aliased clipping/shapes.

    If you run the Web Start demo you can see the GUI in action. Or at least parts of it. Please don’t be disappointed, it is far far from ready yet, but I have made the critical things work, things that required performance to be “enough”. There are still a lot of optimizations left to do. For instance I don’t use Romain Guy’s much faster blur algorithm for calculating the shadows, I use the naive approach with Gaussian blur, which is quite slow.

    The app will need Java 1.6.0_10 on anything other than Mac. On OS X Java 1.5 is fine. I have not tested this on Linux, it will probably look like sh*t. ;) Anyway, most things are just mockups, feel free to click around.

    I will continue to update the app in place as I develop it and the same web start link will be used. Note that there are no media stuff in it at all, so don’t think it will play your mp3s, because it won’t. Yet… The app is signed with an old certificate so you will get a security warning. I will fix that when I get around to it.

    The size of the whole app is 180k, most of it images, and it is pack200 compressed. If you are on update 10 that “.pack.gz” file will be used, otherwise you will have a 400k jar instead…

    Well, enough babbling, just try it and let me know what you think. Is Java always ugly?

    Java Media Player Demo

    Cheers,
    Mikael Grev

    Tags:

  • As you following my blog knows, I have dug down deep into the coding of the GUI. I started there since I deemed that to be the most risky part given Java’s tendency for being slow, unless you know exactly what you do and on which platform. I have coded Swing for a long time so I thought that the problems would be quite a few but I was was confident I could code around them.

    Seems I was wrong, or at least it looks like that right now. Congratulations to those who left comments in the line of “Why Java since it’s so slow and unreliable on the desktop”. The reasons are complicated but I will try to explain them below. Why? Because maybe if I write them down I can solve them? ;)

    First I made a GUI with a few cool, but subtle, effects. I have created the carousel component, the totally customized JScrollBar and both optimized glow and shadow effects. Everything was really fast and smooth, much because of the hardware accelerated image blits and scales. I am very happy with the carousel, it is every bit as fast as iTunes’ Cover Flow.

    The second phase was about getting the side docked pullout sidebars to work. I had several fallback options for this that all should look the same as in the screen shots. And since I develop on the Mac using Java 1.6.0_07 everything went really smooth here as well.

    To enable translucency you just set the background color to a color that have transparency (e.g. new Color(0, 0, 0, 0) and the rest is handled by the Mac Java implementation. I draw the shadows myself since I needed them to look the same for all platforms. It is easier if I make everything as one big window with the pullouts as normal components (and not heavyweight windows). On the Mac this work beautifully, fast and totally seamless.

    Then I switched to test on Windows Vista and XP. There were some initial problems but that was mostly because of me and small inconsistencies that I wasn’t aware of. Like that you need to constantly poll for a new Graphics object from the component you want to animate on Windows. In OS X you could hold on to the same one. No biggie.

    The trick of just setting a background color to get transparency doesn’t work in Windows, not even u10. Not sure why since it is such an obvious way to do it. Instead you have to add two lines, one which is in the protected sun libs. This makes this version update 10 and later only, unless of course I do it using reflection. The lines are:

    window.setUndecorated(true);
    com.sun.awt.AWTUtilities.setWindowOpaque(window, false);

    With those lines pixels that aren’t painted with an opaque color will have the background show through.

    But.. The performance totally went out the window (pun intended). With that last line in the code the GUI turned to dough though. Even selecting a row in the JTable was painfully slow and with a very noticeable lag. Unusable even. After an hour of investigation I found out, not from the documentation mind you, that when translucency is enabled the whole component tree of the frame will be repainted for every little local repaint!!! For instance, when the cursor blinks in a JTextField the whole frame will be repainted. How stupid is that! And not only that, it will be repainted to a buffer and then that buffer will be software copied to the screen! No wonder it was slow..

    OK, I fired up mail to let my favorite Sun engineers know that Java 1.6.0_10 was not bug free just yet. :) I was surprised that they told me that this was the intended behavior! To make things worse they first even tried to convince me that it had to be this way because of how windows works. But after a few emails back and forth it became clear that it is Swing that has a problem with rendering to a translucent back buffer and there were no resources to address that. Bummer… It “may or may not be fixed in an update”…

    So, I though that, well, me being a self appointed Swing/Java2D expert I could make my own back buffer and render to it. If I create my own RepaintManager I can intercept the small repaints and only repaint what is need to my own buffer. Then copy that buffer to the Frame, which in turn will be copied to the screen by Swing. But first I thought that I might do some performance testing, to be sure. It turns out that even a GUI that takes 0.0 ms to render is too slow for any window larger than 800×800 on my 2.4GHz one year old computer. So, even if I made the perfect algorithm that was infinitely fast it wouldn’t be enough. Just add a single JTextField to a translucent window of some size (like 1280×1024) and try to edit it… translucent windows in Java makes GHz feel like MHz. :) Dead end.

    OK, being an expert and all I was not about to give up just yet. I praised OS X’s version of Java for not having any problems in the first place and took a warm shower, which is the place where most of my ideas come to. Ping! New idea!

    I can use the normal window decorations (will look worse, but still ok) and have tool like dialogs for the pullouts. I began testing and at first it looked like it could be done. But it couldn’t… It turns out that there is no way to control the z-ordering of windows/frames/dialogs in Swing. The only control you have is that you can set a Window to be “alwaysOnTop”. Not very usable since that would disrupt the interaction with the other windows on the user’s desktop. Then I tried all the modality modes. You can actually make a tool window float on top of the main window, but not below it! I must have it below since the OS drawn shadow around the Window must be on top of my pullout or it will look very weird. Also, as soon as I pressed the pullout window the main window’s title bar would deactivate which is not the intended behavior. So, dead end there as well and another few hours wasted. And I was out of hot water to get new ideas (OK, not really. (About the water)).

    This is where I am now. At a dead end. I could of course release only for the Mac, but no.. That would go against the whole thing of sharing music with your friends, not many of them have macs…

    Actually when I was writing this I came up with another idea. Not sure it is viable but I might try it. I can set the main window and pullouts to clip with round rectangle shape. No window decorations. That means no problem with z-order or deactivated title bars since I draw the title bar and the windows will not overlap. Of course this means that there won’t be any shadows (not an option) but that might be solved with a kind of shadow-only window that has those much needed translucent pixels. Since those windows aren’t changed much, and they don’t host that many pixels in the first place it might actually work. I’ll think about it some more…

    A lot of wining, I know, but I actually thought Sun would step up to the plate and make Java a viable choice for the desktop. And when I mean the desktop I’m not talking boring enterprise apps with crappy GUIs, I’m talking media players and widgets.

    To add insult to injury it turns out that resizing windows on at least Vista turned sluggish with the jump from 1.6.0_07 to _10. Look at this post for more info: java.net forum link

    Cheers,
    Mikael Grev

    ps. For those of you that come here for the screenshots, if you have managed to get through my ramblings here’s how the Media Player looks right now on the Mac. Everything, including the shadows, is drawn with Java2D (except the album art picture of course) and it is really really fast. Even the volume control is working… :)

    Tags: