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.