Audio Hijack Pro 2.9.1 is Out

February 10th, 2009

AudioHijackPro.png

This morning I read that Audio Hijack Pro 2.9.1 is out with a significant advancement in the Instant Hijack capabilities for 64-bit processes, among other things. I'm sure this has something to do with all the new code that's coming out from developers. With Snow Leopard it'll be even more.

Well... nice to see the improvements.

Microsoft Limiting Number of Running Apps in Low-End Windows 7

February 9th, 2009

pirate.jpg

I was reading Slashdot this morning and saw this post about Microsoft and Windows 7 pricing models - their low-end "Starter Edition" is going to limit the user to running three applications at once. Yikes! I suppose that's OK if you're gaming, but that's a really really small market.

Their research says that the average consumer has just over two applications running at once. Maybe... but I'm not buying that line. Make it 10. What's the problem? Someone working at home and needing the "real goods" is going to up-sell anyway. I just don't get it when they cut these numbers. It makes no sense.

Be the Good Guy, not the Cheapskate.

Sneak Peak at the New Kindle

February 9th, 2009

Kindle.jpg

Well, I'm not shocked, but I am slightly disappointed in the leaked views of the new Kindle. It's nice and thin, and with an aluminum back, it'll be rigid which is nice. But there's a lot of 'border' around the screen, and that really increases the size of the unit.

Also missing is any visible sign of the switches for the 3G modem. Maybe it's in software now, which would be nice, but they may also have made it "always on" - we'll have to wait and see.

For now, this is interesting, and supposedly shipping at the end of this month. We'll see what the details are later today and if they can actually make enough of these to satisfy demand.

Interesting Limitation with Apache 2 and mod_proxy_ajp

February 7th, 2009

WebDevel.jpg

I was rebuilding a few machines today - web servers, that were using the mod_proxy_ajp now a part of Apache to forward the non-static requests to the co-resident Tomcat instance on the box. As a part of that set-up, we had a custom conf file that we loaded into /etc/httpd/conf.d/ to handle all the configuration of the web server. Well... 99% of it, but still - all the proxy forwarding and virtual hosting is in this one file.

The wrinkle came in with a Redirect line in the VirtualHost section of the file:

  <VirtualHost yummy>
      Redirect /index.html http://localhost:8888/yummy/app
      Redirect /UAT http://slushy.funstuff.com:8888/yummy/app
      ...
  </VirtualHost>

where the primary machine has a DNS entry for yummy and that's how most folks get to the web site. The UAT box is called slushy, and this way, the users can hit the URL http://yummy/UAT and get right to the UAT box. Pretty nice.

Or so I thought.

The problem with Apache and the mod_alias, it seems, is the use of localhost in the redirection of index.html to the local machine. When I try to hit it, I get that the web site is not available - like the URL doesn't point to the right sight.

But when I go directly to http://yummy:8888/yummy/app I see the web site - so I know it's there. Also, if I use wget to grab http://localhost:8888/yummy/app on that box, I get the initial page.

It's as if the Apache mod_alias or the mod_proxy_ajp are somehow not using the standard methods of name-to-IP resolution. For if I change the configuration to:

  <VirtualHost yummy>
      Redirect /index.html http://yummy.funstuff.com:8888/yummy/app
      Redirect /UAT http://slushy.funstuff.com:8888/yummy/app
      ...
  </VirtualHost>

Everything works. I looked at the Apache docs for the Redirect command, and it says it needs a fully qualified URL. I have given it that - and verified with wget that it's working. But something in there isn't working.

What this means is that we need to customize these configuration files for each machine so that they can properly redirect to the host it's on. Odd. Very odd. But it's a work-around for now. If this comes up again and again, I'll look into it to see what I might have to do, but very odd.

Neat Little Tip for Faster Flash Startup in Safari

February 6th, 2009

Safari.jpg

I was reading the feeds this morning and came across this wonderful little hint about removing the older version of the Flash plug-in for Safari. I had mistakenly thought that when Flash installed itself, it removed older versions of same, but I was clearly wrong.

The old version was in /Library/Internet Plug-Ins/ and was a file called flashplayer.xpt. I removed the file and restarted Safari and we'll see if I see faster Flash load times. Even if I don't, it's nice to clean out the old dead weight every now and then.

Spare Me the Clever Language Developers

February 5th, 2009

SwissJupiter.jpg

So today I was digging into the custom language code of a vendor's package that was customized by the vendor's consultants for us. The language is designed to be simple and fast to update - everything is based on function calls. Everything.

I can see the advantage - it's a simple function call graph. If there's a value in the tree that doesn't change, then there's no need to make the next level call because nothing is going to change. Seems reasonable, until it's taken to extremes. Like this code.

If you're going to base a language on functions, then you need to have functions that can handle if statements and conversion of variable types: boolean to integer, for example. That's kind of obvious. What this vendor did was to make the bare minimal set of functions that can be used to derive most other things, but there was not care put into it to make the language easy to use.

And they took advantage of that.

Case in point: using a max() function to find the only non-zero value in an array. Why do that? What happens if your assumptions are wrong and there isn't only one non-zero value - say there's two. What then, Sherlock? Yeah, it breaks. Why not be a little smarter and filter out the data and then call the function on the one object you want. Seems pretty simple to me.

But that's not how it was built. It's like they planned on doing a lot of extra work and then "making up for it" in volume, or something like that. It's crazy. No filters means that you have to filter on each value and then pick the max() of the set. What a waste.

Sure, I got it done, but had I been able to write it in a more expressive language, it would have been far easier, and I probably would not have had to go in and fix it in the first place. The original author probably would have gotten it right the first time.

So I spent an hour in Function Land, and I can't say I'm a better person for it. I know it's not the last time I'll have to do this, but I'm hoping that as time goes on I'll be able to remove this horrible code and make it simpler. Like basing it on the non-function-based scripting language they use for everything else. Yeah, it'll be slower, but it will be 100x more maintainable.

Fun with AutoRelease Pools in Cocoa Programming

February 5th, 2009

xcode.jpg

I was talking to a friend today about the use of [[obj alloc] init] and the AutoRelease pools. Turns out, Apple recommends not to use them in iPhone applications. And that got us to dissecting them, to figure out why Apple wouldn't want this very handy feature used in iPhone apps.

First, we need to lay a few ground rules. When I have the code:

  MyObject*  obj = [[MyObject alloc] init];

the reference count on obj is set to 1. What really does this? Well, it's the alloc. Create it (alloc), and it's reference count is 1. Simple rule to remember.

So what if I want to create something, use it in my method, and then get rid of it? In these cases, you know the lifetime of the object is within the scope of your method, and in that case, you can choose to use the more efficient:

  MyObject*  obj = [[MyObject alloc] init];
 
  // ...use this guy for anything you need
 
  [obj release];

the last line in the code sample balances the alloc in the first line and reduces the reference count by one, and when zero, the object is removed. Easy. But this is very 'manual' - a lot like the C malloc() and free(). But it is efficient. So you just have to decide what's more important - efficiency or a little leeway on the object lifecycle?

For example, say we might want to keep this, but we might not. Then what? If we had written the code like this:

  MyObject*  obj = [[MyObject alloc] init];
 
  // ...use this guy for anything you need
 
  // if we have no error, keep this guy
  if (!error) {
      [self setObject:obj];
  } else {
      [obj release];
  }

Now the question becomes Can't we make this cleaner? and the answer is you bet we can:

  MyObject*  obj = [[MyObject alloc] init] autorelease];
 
  // ...use this guy for anything you need
 
  // if we have no error, keep this guy
  if (!error) {
      [self setObject:obj];
  }

with the addition of the autorelease call, we have placed this instance into an NSAutoreleasePool and at the end of the next run loop, it will clear out the pool, calling release on each item in the pool, and those whose retain counts hit zero are going to be freed.

Why is this better? Well... because when we create it, we can put it in the state that says "Hey, if I don't do anything with this guy, clean him up, but leave me the option to keep him." This, of course, is not as efficient as the first case, but this is far more flexible. If there are times when you might need to keep ahold of something you've created, this is the cleaner solution.

There's also the question of the Factory Pattern. If I'm making things for (possible) consumption, then I need to autorelease them before I return them. This allows the caller to either retain them or not, and if not, then at the end of the next run loop, the NSAutoreleasePool will clear it out and be done with it.

Remember, calling autorelease doesn't change the retain count - it just puts it in a pool that eventually will release the object and then possibly free it. So, it's in the definition of eventually that the inefficiency comes it.

In general, it's a decent idea to do [[[obj alloc] init] autorelease] if you're making a few dozen things at any one time. The NSAutoreleasePool doesn't get too bug, and it's cleaned up easily enough. Also, it gives you the option of having the same initializer code for those things that might stick around, and for those that won't. But make no mistake, it's not as efficient as not using it and careful scoping of the instance lifetime.

This seems to be the point with Apple on the iPhone. It's not as efficient, and with all the things on that little guy, resources have got to be at a premium. So, if you can control the scope of your instances, then do the simpler [[obj alloc] init] with a release when you're done. But if you can't do that, then use autorelease. Just realize the impact to your application.

As a final note, here are some interesting examples of where autorelease helps. Imagine that we have the following code where we create one object, hold on to it, create another, and then message the first. This would be recognized by a C coder as the classic dangling pointer:

  MyObject*  obj = [[MyObject alloc] init];
 
  // ...use this guy for anything you need
 
  // hold on to him for a sec
  MyObject*  holder = first;
 
  [obj release];
 
  // make another - maybe with different parameters
  obj = [[MyObject alloc] init];
 
  // ...use this guy for anything you need
 
  // message the first - and it'll blow up
  [holder doSomething];
 
  [obj release];

this guy is going to blow up because the original instance is long gone, but the pointer is still being held in holder. This seems obvious, but there are tons of ways you can get yourself into this bind by managing the release yourself. You have to be very careful if you're not using autorelease.

But in the iPhone, you have to try.

[2/6] UPDATE: I knew there was a good reference on this topic. This is from an old Stepwise.com posting in 2005, but it's as true to day as then. It's got great coverage of all the rules. Certainly something to keep handy when you get a little confused about the topic.

17″ Unibody MacBook Pro Delayed

February 5th, 2009

MacBookPro17.jpg

I read this morning of a letter sent out by Apple to the initial orders on the 17" Unibody MacBook Pro:

To Our Valued Apple Customer:

Thank you again for your order! Wrapping up the new 17-inch MacBook Pro is taking a few days longer than we projected. As a result, we will be unable to ship your 17-inch MacBook Pro until February 19, 2009.

While mine is still slated to be shipped Feb 23rd, I have to wonder if there's going to be a problem that impacts that shipping date. Don't know. We'll have to wait and see. It's not like I'm not going to wait for it.

Apple Updates GarageBand ’09 on Software Update

February 5th, 2009

iLife09.jpg

Turns out, there was a slight problem with the "Learn to Play" feature of GarageBand '09 - and so today Apple released an update to GarageBand on Software Update. I haven't used GarageBand, but it's possible I might. The kids are getting a few new instruments and it might be interesting to be able to show them how to get some background music for their tunes.

Gotta love that Software Update...

A Kick in the Teeth Always Hurts – No Matter Who You Are

February 4th, 2009

cubeLifeView.gif

I can't help but feel sad for a guy that I've been working with for over seven years. Yesterday, he was "let go" by the trading-side of the business, and then offered a job on the development-side of the shop. Don't get me wrong, I think he'll be a fine developer. But getting that one-two punch in the gut yesterday had to hurt. I don't care who you are.

We can all be pushed to our limits and show our less wonderful sides to people. It's what happens. Stress causes us to get more "kill or be killed" and that, in turn, suppresses our kindness and tolerance for others, and we show a face to others we might not want to show. It's happened to me, it'll happen again. It's happened to this guy, and it had to be a contributing factor in his getting released from the business-side.

The reason I feel for this guy is that becoming a developer for him now is a nice landing, but it's like having once been a Vegas Headliner and then going back to teach elementary school kids how to sing and dance. It's a huge blow to the ego. I don't care who you are.

Some may certainly get over it faster than others, but we're still in the first 24 hrs. and that's definetely in the "ouch" phase of this particular life-lesson. I just wonder if management is really thinking he's going to stick this demotion out. Sure, the economy is not strong, but this is the financial sector, and there always seems to be jobs out there - someone is making money. If not on the market, then on the volatility. So I wonder if he's going to stick it out.

I hope he finds what he's looking for. Whatever that is.