Category Archives: Technical Stuff

A Music Server

So I’ve been wanting something to replace the music in our house for quite some time. We bought wireless speakers several years ago that are fantastic for parties and having kids (moving to another room? just pick up the speaker and go). The problem has been getting a stereo that works with them. And with an iPod. And with CDs, and it’s been a mess. So here’s what we’ve tried that we decided didn’t work quite how we wanted.

  • Having all mp3s on Playstation 3. Clunky interface. No control via iPod/Android.
  • Streaming to Playstation 3 using UPNP – too slow. No control via iPod/Android. Needs separate dedicated music server.
  • Dedicated music server hooked directly to wireless speakers. Cost for new system. Energy usage.
  • Stereo with iPod dock. No android support. iPod docks stop working.

So I began playing with my router and noticed I could put PHP on it. I decided to setup a web server to play with and in doing so, noticed that DD-WRT/OpenWRT had sound support. Puzzled, I looked it up and turns out I could plug this:



into the USB port on the back of my router and have sound. Intrigued I tried plugging in a USB hub and a USB hard drive with the sound card, and was able to get all my MP3s on the router with sound output.

I started writing my own interface, but found out there was already a program called MPD (Music Playlist Daemon) compiled for the router that had iPhone and Android control apps. So now Julie and I can walk around our house, pull out our phones and start, stop or change the music. And it’s all running off a router that was always on anyway. No music stopping because Tim has to reboot his computer.

Here’s the partlist if you’re interested in replicating it yourself:

Evil Java Interview Question

class Fruit {
    public Fruit() {
       init();
    }
    protected void init() {
    }
}
class Orange extends Fruit {
    private String color = null;
    public Orange() {
        super();
    }
    protected void init() {
        color = "Orange";
    }
}

If I create a new instance of Orange what is the variable ‘color’ set to? The answer is null.

.Net is a sign

So it came out today that the company that screwed up the appliance rebates in Texas this week had already screwed up in two other states.

But there should have been one big warning sign before that. The fact the firm handling the rebates was using .Net.

Now there are definitely good programmers working in .Net. And you can definitely built working websites with it. I’ve heard from good programmers who’ve done it. But it’s not where the energy is, and .Net seems to be drawing the unemployables. The programmers who can’t get a job anywhere else. The money is in Java. And the excitement is in Ruby, Python, and PHP. .Net positions exist… for other reasons.

And this was pretty obvious when under load they didn’t immediately remove images and other externally loaded static resources. This group didn’t even have the most basic of solutions to the problem in their toolkit.

So while it’s possible that firm you’ve hired that wants to develop in .Net is competent and has some fantastic programmers, chances are that it’s not. And it doesn’t.

Interactivity and Waiting

So I installed a system software update on my PS3 last night and had to wait for it to install. Julie and I wanted to watch a Netflix movie, and it’s tedious that I have to update something on my PS3 pretty much everytime I want to use it, but that’s a rant for another time.

So anytime I install a PS3 software update it always creeps very slowly up to 61% then jumps to 100%. So I’m quite confident the bar is a sham. This got my brainstorming.

Why couldn’t the bar respond to input? Like have it install a second slower per percentage, but if I bang on the buttons or shake the controller the bar moves faster. Make me feel like I have some control over the situation!

Which then made me think – couldn’t you provide me with a simple game like Soduku or Minesweeper to play while I wait.

Which made me think of Noby, Noby Boy where I get to fly a butterfly around the screen while I wait.

I know we want to look “professional”, but I’m sure that customers wouldn’t complain if they weren’t FORCED to go get coffee when they started an install.

Javascript Performance

So at work I had to fix the performance of an AJAX call. It was using a java library called AjaxAnywhere to completely replace a table. When it did that with thousands of rows it got REALLY slow.

It was simply replacing the table with innerHTML, and I figured if I changed it to using dom methods it would be faster. It didn’t due to what I’ll discuss in the third bullet point. But I learned a few other lessons about performance along the way.

1) Copy your array length to a local variable:

This is much slower:

for(var i = 0; i < someArray.length; i++) {
  // do something
}

than this:

for(var i = 0, il = someArray.length; i < il; i++) {
  // do something
}

2) Don’t use prototypes object creation functions in loops (I think prototype object creation works great for the small stuff, and is very legible). They’re too slow. I started out with this:

var tr = new Element("tr", {
  'class': 'unselectable',
  'id': idValue
});

but it turns out that prototype adding attributes via a hash (what Element.writeAttribute does) looks up the dom node each time, which is a performance drain. I changed it to this:

var tr = document.createElement("tr");
tr.className = 'unselectable';
tr.id = idValue;
 

3) Create a render queue. It took me a long to find this, but you’ll probably run into it no matter how fast your javascript runs. Generally web browsers wait until your javascript function exits to update the dom. If you’re adding thousands of objects your page can blank for seconds redrawing. What’s the answer? A render queue, which looks something like this (posting as a nice class as I don’t think there are enough examples like this):

var lgt = lgt || {};

lgt.RepetitiveTaskManager = function() {
};

lgt.RepetitiveTaskManager.prototype.renderQueue = Array();
lgt.RepetitiveTaskManager.prototype.rendererRunning = false;

lgt.RepetitiveTaskManager.prototype.enqueue = function(methodRef) {
  var renderQueue = this.renderQueue;
  renderQueue.push(methodRef);
   
  if(this.rendererRunning == false) {
    this.rendererRunning = true;
    setTimeout(this.renderer.bind(this), 1);
  }
}

lgt.RepetitiveTaskManager.prototype.renderer = function() {
  var renderQueue = this.renderQueue;
  var length = (renderQueue.length > 5 ? 5 : renderQueue.length);
  for(var i = 0; i < length; i++) {
    var functionCall = renderQueue.shift();
    functionCall();
  }
    
  if(renderQueue.length > 0) {
    setTimeout(this._renderer.bind(this), 1);
    return;
  }
  this.rendererRunning = false;
}


// first declare our renderer function
var callback = function(table, cellContents) {

  var tr = document.createElement("TR");
  var td = document.createElement("TD");
  td.innerHTML = cellContents;
  tr.appendChild(td);
  table.appendChild(tr);
};


// now add 1000 rows to a table

var taskManager = new lgt.RepetitiveTaskManager();

var table = document.getElementById("myTableId");
for(var i = 0; i < 1000; i++) {
  taskManager.enqueue(callback.bind(table, i));
}

Don’t forget bind is your friend in this case. For those without much experience with it, bind let’s you pass a function call with the appropriate variables to call the method with, without calling the method at that exact moment.

By using this render queue it will render 5 rows at a time on the page, and the table will seem to expand down the page as the user watches. This isn’t desirable in all case, but it’s generally better than having the user’s browser get unresponsive.

New Laptop

I forgot to mention that this weekend I also got a new laptop. We found an Acer Aspire 5600 on a pretty good discount at Circuit City. Not a place I normally shop, but this time the experience was actually pretty good. Not that they had the laptop on display anywhere, nor did anyone attempt to help us, but the check out guy was really friendly. I realize I have set the lowest possible bar for that store, but I was still pleasantly surprised when they managed to meet it.

It’s a 1.6Ghz Core 2 Duo with 2GB of ram. The main reason I went with Acer is that all the parts are fairly generic intel parts and so they should in theory work well with linux. Shockingly enough when I installed Ubuntu (Gutsy Gibbon) everything came up properly. I was able to scan wireless networks and connect to my father’s WPA encrypted one without editing a single configuration file. Everything came up perfectly with no futzing with the exception of the multimedia hotkeys and the built in webcam.

The webcam was just a matter of finding the right driver (uvcdriver) and software (luvcview). I did have to build a kernel module and setup some options for it, but c’mon that’s small potatoes. Oh, and I had to turn off 3d effects temporarily or the program would crash. But let’s be honest, I was just being obsessive. The chance of me actually using a webcam frequently is pretty slim.

The hotkeys required a separate kernel module acerhk. I ran it with the options ‘force_series=6000 probe=0 verbose=4’ and everything worked great.

While that might seem like a lot of work in 2 days I’ve managed to get a linux laptop fully functioning. I had my last one for 3 years and it often wouldn’t let me connect to wireless networks which I think is a major problem. I could never use a GUI with my networking, I was constantly editing files and bringing up and down services. No more. It’s wonderful. I feel like I could actually hand this laptop to a non-technical user and they’d have no trouble with it. Plus it has cool 3d effects when I shuffle windows around.

All in all, I’m really happy with it. It’s speedy, has a wide screen and I LOVE not having to muck around with wireless.

Tonight I go to help Ashly and Tarv install fans. Julie and Stella are coming along so it promises to be exciting. Wish me luck.

Comments

I think I might have gotten comments working so that you guys having problems can actual hit the submit button. Feel free to email me if it still doesn’t work.