For some odd reason, many people seem to be living in the past when it comes to Java performance and capability. I myself have been surprised on occasion at what it's capable of, such as this afternoon.
I like TV, and am working my way towards being a professionally paid writer. Great authors always say that if you want to write good books, you have got to read good books -- constantly. You have to love to read, or you won't have any kind of sense of what makes a story great. Television is the same, though I find it much more difficult to explain to people that when I sit down in front of the TV, I'm actually working.
For me, a Digital Video Recorder is a must. I wanted a TiVo from the first day I heard about them, and one of my friends has been working there after moving from SGI since the earliest days.
Unfortunately, I happen to be something of a miser. I won't buy games that require monthly fees to play, and I won't buy a DVR when I have to pay money every month in order for it to keep working. It's just not going to happen.
It took a while, but I finally gathered all the parts I needed for a low-end PC that would serve as my Personal Video Recorder, or PVR. Today it is much closer to a low-end Home Theater PC, in that it has an AMD XP 3000+ processor which just happens to be a tick faster than the Intel P4 in my desktop.
It records very good quality video, but not quite as good as the custom hardware that makes up a commercial DVR. The hard drive is large enough to hold on average about 60 or perhaps 70 hours of video, and periodically updates the electronic program guide on its own. It's networked, of course, so I can burn anything I record.
My main complaint with this setup is the software. Because the video card I have in that machine is quite old, it isn't properly supported by X Windows when it comes to hardware overlay. This means that while programs appear to display normally, video only runs at roughly one frame every three seconds or so.
This has forced me to use Windows XP as the operating system, instead of Linux, and limited my choices for DVR software to three packages: SageTV which is written in Java and a mix of C libraries, Beyond TV -- both of which cost money -- and the free but flawed GB-PVR.
I'm sticking with GB-PVR because it's free, and does its job 90% of the time, but that last 10% is so incredibly frustrating that I've been taking time away from writing lately to begin forging my own DVR software.
I've ventured into this territory before, and hit road blocks that would have made the effort required to get it done far outweigh the benefit of not having to deal with that troublesome 10% anymore. Chief among these is the way in which you record video on the Windows platform.
The only way to get it done is via DirectX, and not all video capture card manufactures are forthcoming with how to use the drivers they install for their own bundled software. My chief problem was the inability to use DirectX to change the capture bitrate -- basically the main video quality setting -- with program code.
I could instruct the driver to display an input box to the user, whereby the user could make these changes on his or her own, but that is a hack that I wasn't willing to put up with. I contacted my capture card manufacture as I've heard that they are open to sharing the necessary information and code with developers who are willing to sign a non-disclosure agreement, but they simply ignored my request.
So that project ended abruptly a few years ago, with a virtual driver I had written that was fully capable of capturing video from the card, but unable to modify quality settings. Fast forward to today, and I have found an open source project that has the code I needed back then, and it is freely available today.
So once again, I set out to build my own DVR software, and my choice for this project was Java.
Because of the platform-specific nature of video capture, the one benefit of Java that it is most famous for is also the one feature that wouldn't benefit me at all -- the ability to run on multiple platforms without recompiling the program or dealing with platform specific APIs.
That's fine, because like most of my programming projects, I don't expect to ever finish it, much less make a concerted effort to release it to the public and market it as competition to the other suites currently available.
The first order of business is writing the graphical interface that people, or more accurately I, would see on the television screen. Naturally you navigate these things with a remote control, so you can forget about intricate point-and-click designs with radio buttons, sliders, and the like. This is strictly an up-down-left-right and click interface where just about anything you are going to be doing will have its own screen.
Not only does this make it easy to use, but it also allows you to maximize the limited space available for what need to be super-sized components so you can read them at a distance of five feet or more.
Java was originally designed for set-top boxes, so you'd think that a project such as this would be a natural fit, but to be truthful, I've found that Java has been totally geared towards desktop PC design more than anything. And that's great, because interface design with Java is exceptionally easy to do, and rarely breaks. These days, it's often as responsive as native applications are.
When you go back to my design specifications, you need a left-set menu of buttons that you navigate up and down, and a right-set pluggable widget that will take up most of the screen realestate. That widget will be directly related to the screen you are on, for instance an electronic programming guide, or a vertical list of pending recordings.
Sounds easy enough, and I suppose that's the case when you've done something like this before. I for one have not. I am not a programmer by trade, and am not professionally trained in Java, or any language for that matter. This is not to say that I'm inept, far from it. I can code proficiently in Java and C, and script in both PERL and PHP, as well as a moderate amount of SQL.
My experience can probably best be summed up by saying that I go in, get what I need done, and then get the hell out. I don't stick around for the best practices unless it comes to security, which I do take seriously.
Object Orientated Programming was something that took me longer than I'd like to admit to understand, but eventually I did get there. Still, I feel most at home with C, and that hasn't been more evident than right now.
I know from past experience writing a rather bloated yet functional screen saver in Java that sometimes the best way to get something done quickly is to forgo using higher level interfaces like Swing in favor of the very basic functions that the Abstract Windowing Toolkit provides.
It can be described like painting on a blank canvas. You can, if you wish, create a window with a black background, and just draw on it like a doodle toy. You can draw privative shapes, and textual strings directly on the window canvas itself.
Of course you lose a great deal in the process. Text strings don't wrap, and if allowed will simply trail right off the canvas and disappear. Few interfaces would be acceptable when made up entirely of white rectangles, either. On top of that, these are now just two-dimensional drawings that you can't interact with, at least not by default.
If you create a Swing button and place it in your window, you can click on it and see it respond by changing its appearance right away, and you don't have to do anything to get that effect. When you draw things yourself, you have to recreate that functionality, and lose an incredible amount of time in the process.
I got into the interface design this way and paid the price, I found that laying out elements like simple buttons was easy enough, but controlling their behavior became extremely complex. One can often take for granted the thousands of classes and probably millions of lines of code that you never see or interact with, and you lose sight of what a life saver it all can be.
Suffice it to say that at some point I realized that reinventing the Java class library was not in my best interests, and ended up tossing out a lot of code, but there were other reasons for doing this that have shown me the power you can get out of standard objects like buttons, if you take the time to extend them a little.
GB-PVR uses XML files so "skin" the program, such that you can change the color and visual appearance of most of the menus to your liking. Because I have modified the base skin before, I had personal experience with the benefits this provides, so I wanted to have that functionality myself.
I took this to the next level, or at least tried to, by using XML files to actually build the screens themselves, and to some level dictate their operation as well. The initial design allowed you to place virtually any visual widget/element that the program could create on any screen, in any place, with any look.
At first, any button could have its own image background, and you had full control over the font text as well. Font family, size, color, you name it, you could control it. You could draw buttons anywhere on the screen that you wanted, which was great because it meant you didn't have to recompile the program while being able to redesign the entire menu system from scratch.
That kind of abstract control is well within Java's capability, but I quickly found that it wasn't really within my own capability, nor was it an ideal solution.
The thing about that kind of setup is that you are going from the ability to create visual themes to building a primitive scripting system that dictates how the program operates, which really isn't what you want. Those smaller external elements should tweak and extend and modify, but never control the core program.
One reason this is a bad idea is how convoluted the program becomes. My base "screen" class was meant to be as generic as possible. That class would read any XML file you give it, and build the screen the XML file tells it to, and then it would display itself. In order to support that, the base screen needed to have an instance of every single widget the system supported, so it could initialize and display it.
This worked great at first, when none of these widgets actually did anything and there were only a couple of them. The XML told the class what to display, and it did, and that was great. Then I had to make my custom button widgets actually do something, like respond to keyboard events.
The code necessary to make one button display a special image when it was active, and to move to the next button when up or down arrow was pressed was added, and the XML was updated to encompass these buttons in a menu of sorts, which was just a container that served to give the buttons a common hierarchy.
That was all well and great, but I found myself reproducing functionality that already existed within Swing. I had to write code that kept track of what button had focus, so I knew how to properly draw each of them, and putting them inside a menu object helped, but only so much, because then I had to build out that menu object to do a lot of grunt work that was bloating the screen class.
At that point I was also breaking out of good design patterns. These objects such as the buttons were incredibly simple, so they didn't support listening for certain events like key presses, only the window itself had that capability. I ended up having to put the logic to deal with key presses in the containing window for all of the buttons, and the menu, and it was only going to get worse from there.