ambient reality

pimping code and tech crap

Monday, March 20, 2006

Creative: Makers of the Best and Worst Sound Cards

I set out to build a home theater PC and when it came time to select a sound card, the choice was simple: Creative SoundBlaster. I wanted it to have several outputs such as optical and coax, so there was really one option, the SoundBlaster Audigy 2 NX.


After hooking it up to a Windows XP Media Center Edition PC, I noticed that it started to distort the sound and cause videos to be jerky.

I finally got fed up and went and bought a SoundBlaster X-Fi XtremeMusic and let me tell you, this card kicks ass!


It only has digital out, front, rear, and center/sub outputs, plus a gameport. There's no mic or line in. The surround sound is amazing and clear. I highly recommend the X-Fi, so go buy one right now. I can't wait to play a little Doom3 with the lights out.

Tuesday, March 14, 2006

Adventures in BIOS Flashing & Live CDs

Last October I went on a shopping spree and bought a bunch of crap including a server that I was going to turn into a firewall. Well, I finally assembled this server and fired it up. Immediately the BIOS starts beeping at me. After Google'ing the error message "Unknown BIOS error" with the error code 0163, I discovered it was because my Sempron 2800+ CPU was too new for the BIOS.

So begins the fun. Updating the BIOS on an ASUS motherboard sucks ass. Finding the latest BIOS update was easy. Installing it is a whole other issue.

There's two ways to update the BIOS: a program called AsusUpdate that only runs in Windows and another program called AFUDOS that only runs in DOS. Simple, if you have Windows installed, but I didn't have an OS installed. I also didn't bother to install a floppy drive in this server, so...

Enter the Live CD. I started by downloading Bart's Preinstalled Environment. After installing it, run the PEBuilder, insert your Windows XP SP2 disc, pick a custom folder to dump onto the Live CD (i.e. the AsusUpdate and the update ROM) and specify the output ISO file. From there burn the ISO, slap it in the server, boot up a very watered down version of Windows, run the AsusUpdate program and smile as you stare at a dialog box that doesn't say shit. Clicking OK caused the installer to exit and leave a bunch of crap in the temp folder.

Ok, no problem, lets try Bart's DOS live cd. First you need to download like 4 seperate files, decompress and assemble them. After totally messing up the first CD, I figured out how to hack the files together. I added the AFUDOS program and the ROM and finally burned a cute little CD from the generated ISO file. I slapped this disc in the server and booted it up. Finally got the updater to work and I needed to reboot.

After the system booted up and hitting F1 to confirm the BIOS message that the CMOS is messed up, somehow everything started working. The BIOS now recognized my CPU and finally I could install my firewall, but that another story.

In short, Asus BIOS are a huge pain to flash if you don't use Windows and Bart has really kick ass and super handy bootable CDs.

Monday, March 06, 2006

Javascript Inheritance

Igor, I've done it! I've come up with the most pimp way, IMHO, to do inheritance in Javascript. After doing some research, I found lots of interesting approaches, but I didn't particularily like any of them.

Douglas Crockford and Prototype extend the built classes with helper functions which is can be dangerous. Kevin Lindsey's uses the more common method of setting the object's prototype to a new instance of the extended object, but incorporates a superclass for accessing the base class. Harry Fuecks seems to agree that this technique is not the best. Harry seems to like Troels Knak-Nielsen's technique, but I wanted something even cleaner, easier and self contained.

So, after some lots of thinking and coding, here's what I came up with:

function Class(obj){var f=function(){for(i in this._bi)this._bi[i]=0;if(typeof(this.construct)=='function')this.construct.apply(this,arguments);};f.prototype=obj;var fp=f.prototype;fp._bi=[];fp._bo=[];fp.base=function(fn){if(fn){var args=[];for(var i=1;i<arguments.length;i++)args[i-1]=arguments[i];for(var b=this._bo;this._bi['_'+fn]<b.length;this._bi['_'+fn]++)if(typeof(b[this._bi['_'+fn]][fn])=='function')return b[this._bi['_'+fn]++][fn].apply(this,args);}};if(arguments.length>1){for(var i=1;i<arguments.length;i++){var e=arguments[i].prototype,b=fp._bo.length;fp._bo[b]={};for(p in e){if(p!="base"&&p!="_bi"){if(fp[p]){if(p!="_bo"){fp._bo[b][p]=e[p];fp._bi['_'+p]=0;}else fp._bo=fp._bo.concat(e[p]);}else fp[p]=e[p];}}}}return f;}

Here it is expanded:

function Class(obj){
    var f=function(){
        for(i in this._bi)
            this._bi[i]=0;
        if(typeof(this.construct)=='function')
            this.construct.apply(this,arguments);
    };

    f.prototype=obj;
    var fp=f.prototype;
    fp._bi=[];
    fp._bo=[];
    fp.base=function(fn){
        if(fn){
            var args=[];
            for(var i=1;i<arguments.length;i++)
                args[i-1]=arguments[i];
            for(var b=this._bo;this._bi['_'+fn]<b.length;this._bi['_'+fn]++)
                if(typeof(b[this._bi['_'+fn]][fn])=='function')
                    return b[this._bi['_'+fn]++][fn].apply(this,args);
        }
    };

    if(arguments.length>1){
        for(var i=1;i<arguments.length;i++){
            var e=arguments[i].prototype,b=fp._bo.length;
            fp._bo[b]={};
            for(p in e){
                if(p!="base"&&p!="_bi"){
                    if(fp[p]){
                        if(p!="_bo"){
                            fp._bo[b][p]=e[p];
                            fp._bi['_'+p]=0;
                        }else
                            fp._bo=fp._bo.concat(e[p]);
                    }else
                        fp[p]=e[p];
                }
            }
        }
    }

    return f;
}

Basically, it's a function that build's your neato class. The first argument is an object for this class, then you can optionally pass in as many other objects which will be extended.

When this function is called, it creates a new anonymous function and then sets the function's prototype to the object defined by the first argument. Then it needs to create two arrays for dealing with base objects and the method to invoke the base method. Finally the class is extended with each additional object passed in.

I used Kevin Lindsey's example as the base for my examples. We first start by defining our base Person class. You'll notice the first argument I'm passing an inline JSON object. I prefer this because it looks clean and you could also eval() an XMLHttpRequest response inline. Ooh, sexy!

var Person=new Class(
    {
        construct:function(first, last){
            if (arguments.length > 0)
                this.init(first, last);
        },
        init:function(first, last){
            this.first=first;
            this.last=last;
        },
        print:function(){
            return this.first + "," + this.last;
        }
    }
);

var p=new Person("Chris", "Barber");
alert(p.print());

So far this will alert "Chris,Barber". Cool, so next extend the Person class and create the Employee class.

var Employee=new Class(
    {
        construct:function(first, last, id){
            if (arguments.length > 0)
                this.init(first, last, id);
        },
        init:function(first, last, id){
            this.base("init", first, last);
            this.id = id;
        },
        print:function(){
            var name = this.base("print");
            return this.id + ":" + name;
        }
    },
    Person
);

var e=new Employee("Chris", "Barber", 13);
alert(e.print());

Now we get "13:Barber,Chris. Finally we create the Manager class.

var Manager=new Class(
    {
        construct:function(first, last, id, department){
            if (arguments.length > 0)
                this.init(first, last, id, department);
        },
        init:function(first, last, id, department){
            this.base("init", first, last, id);
            this.department = department;
        },
        print:function(){
            var employee = this.base("print");
            return employee + " manages " + this.department;
        }
    },
    Employee
);

var m=new Manager("Chris", "Barber", 13, "Engineering");
alert(m.print());

Lastly we are alerted "13:Chris,Barber manages Engineering".

You can easily extend more than one class by just passing in more objects.

var myObj=new Object();
myObj.mystuff="goes here";

var MyShibbyClass=new Class(
    myObj,
    Widget,
    Gizmo,
    Something
);


I ran this through a bunch of tests and everything worked pretty good, but there are a few rules:
  • To call the super method, you must use this.base() and pass in at a minimum the mehod name
  • You must not call the this.base() more than once per method (like you'd do that anyway)
  • The constructor must be called "construct" (I wanted to call it "constructor", but it was a reserved word or something)
  • You should not name your methods using reserved words (i.e. tostring, constructor, class, etc.)
I've tested this in Firefox 1.5, Mozilla 1.7.5, Opera 9 and IE6 all on Windows XP and they all work. I'm curious how Safari or Konqueror handles this method.

As for performance, I haven't benchmarked it, but I have to believe this is pretty damn efficient as far as bandwidth and memory is concerned.

I don't know if this method has been done before, so let me know if this something new or old. Feel free to use it for whatever. Don't be evil!

Saturday, March 04, 2006

The AJAX Experience Conference

I just registered for The AJAX Experience yesterday. Friday was the cutoff for the early bird special price of $1095. I don't know what I'm looking forward to more: the conference or the weather. I haven't been to San Francisco since I was a kid, so it will be fun. There's a great line up of speakers and the topics sound very interesting. My day job requires me to code in .NET/C#, but at night, I've been brushing up on my JSP/Servlets. I was kind of surprised to see that a lot of the sessions use Java for the server side. I actually prefer Java over .NET. The conference isn't for another 2 months. I'm paying the whole trip out of my own pocket and I estimate that it'll cost me close to $2,500, so this better be worth it. So in the meantime, I get to do extremely shibby stuff with Javascript.

Monday, February 27, 2006

PSP Web Development Part 2

I spent sometime over the weekend doing some more PSP web stuff and found more issues. First off, you can't do any DOM stuff like createElement and appendChild. Second, you can't do XMLHttpRequest, so that rules out any AJAX stuff. I tried scrollTop on a textarea and that didn't work. No idea if it works for the window, div's with overflow or iframes. On the bright side, it seems to have good CSS support. I spoofed my Firefox's user agent using the PSP user agent "Mozilla/4.0 (PSP (PlayStation Portable); 2.00)" and hit the official Sony PSP site http://psp.us.playstation.com. There site is not what I would consider lightweight. It's got a lot of code. That might explain why it felt a little sluggish. Hover events lagged a second behind the pointer movement. Another issue that may limit the imagination is the amount of memory. The PSP has 32MB of RAM. I don't know how much RAM the browser eats up, but if you have the cache set to 2MB and all 3 tabs open, I can definitely see the device running out of memory. As far as input is concerned, I know onclick events work. I've read that onmouseover, onmousemove and onmouseout work too, but I haven't tested it yet. Texting is still a problem. The keypad entry screen is pretty horrible if you wanted to type an email. A company called Logic 3 was working on a keyboard for the PSP, but was recently axed. Hopefully Sony will come out with some sort of keyboard because the keypad sucks. I'd like to play around with building an on screen keyboard similar to how old Nintendo games worked. I've seen a couple PSP websites use this method, but I think it could be improved.

Thursday, February 23, 2006

PSP Web Development Part 1

Tonight I had the opportunity to do a little web programming for my Sony PSP. Ever since the 2.0 firmware update (I think), they've had a web browser built in. After running a bunch of tests, I've concluded that it's actually a decent browser. Heck, I'd go as far as to say it's better than IE6. These are the tests that passed with flying colors:
  • CSS positional elements
  • GIF, JPG and PNG support
  • PNG's with opacity
  • Javascript related
    • document.onload
    • document.getElementById
    • Setting innerHTML of a non-empty div
    • alert dialogs
    • setTimeout animations
The following did not work as expected:
  • Overlapping divs with opacity
  • Setting innerHTML of empty div
I'm hoping to do some more advanced stuff with DHTML, DOM, input capture (d-pad, buttons) and CSS.

Monday, February 20, 2006

Developing Java web apps

It's been years since I last did a web application in Java. In the past, developing Java web apps was simple and painful. You had to roll your own library to do almost everything. Fast forward to today. Java grew up... bigtime. It's amazing how much .NET and Java are alike. Both have abstracted controls, code behinds, interactive debuggers, blah, blah, blah. So, I set out to build a simple JSP website with some Servlets. The first thing I needed to do is find an IDE worth a crap. I tried NetBeans 4.1. Just creating a project is problematic. The stupid project wizard kept messing up when I specified a folder off the root. Next I tried Eclipse 3.1. I was able to create my project, but then I got pissed off for some reason that I can't recall and decided to see what else was out there. Then I tried Sun Java Studio Creator 2, which is based on NetBeans. I created my project and unlike NetBeans, it actually worked. It kindly creates a directory structure to help organize your files and adds a bunch of crap to the project. To get Tomcat to serve the files, I pointed the document root to C:\myproject\web. I had serious problems. Libraries weren't found, nothing worked. Then I noticed that there was a directory C:\myproject\build\www. Point Tomcat's / context to that path and bingo! So far so good. Now I needed to create a simple JSP file called index.jsp. Adding a file will automatically generate this JavaBean code behind file that is used for JSF stuff. I don't want that crap. If you delete the index.java file, it kills the JSP file. WTF? Stay tuned... I'll figure this crap out eventually.

How to print an iframe

To print the contents of an iframe, use this code: <iframe name="myiframe" src="myurl"></iframe> <script> if (!/MSIE 7\./.test(navigator.userAgent)) {     var f = document.all ? window.frames["myiframe"] : myiframe;     f.focus();     f.print(); } else {     alert("IE7 sucks and so do you for using it."); } </script>