Binary Code

A whole lot of nought thought by Chris Cummer

Paying vs. Pirating

Over in the Ottawa Citizen, Kate Heartfield writes in “Please, let me pay for that movie”, a poignant op-ed piece, that quite a lot of people who might be inclined to pirate content would really rather pay for it. I concur.

As they say, “the plural of anecdote is not data”, so take this for what you will, but here’s a small illustration from my perspective:

The other night my girlfriend and I were browsing on iTunes for a movie to watch. Rather flippantly she mentioned she’d never seen 300 before. This, to me, is unthinkable. 300 is an awesome film, faithful to the graphic novel, beautifully shot, and thoroughly enjoyable.

I actually own 300. The very DVD was sitting on a shelf in the other room, not five meters away, probably unwatched since the day I bought it.

“Get the DVD”, I thought as I started to rise from the couch. But then it occurred to me: watching that plastic platter would mean turning on the Xbox, switching the TV context, sitting through all the anti-piracy crap and ads at the beginning of it and, perhaps least-appealing of all, actually getting off the couch to go fetch the thing itself. The DVD was in another room, nowhere near the kitchen or bathroom. It would be a journey of singular utility, marginal utility.

I sat back, I clicked “Purchase” in iTunes, we started watching it immediately. And it was good.

Some might infer from this tale that I’m so lazy I’ll pay for something I already own instead of exerting additional effort. They would be correct, but that’s beside the point so let’s just… nothing to see there, move along. My real point is this: when payment is the easiest, most friction-free approach to acquisition, payment is often the preferred approach. During the day I trade my time and knowledge for money, and at night I’ll happily trade my money for convenience and entertainment.

Finding pirated content is a pain in the ass. Downloading torrents is a pain in the ass. Re-encoding the resulting MKV or AVI files for iTunes is a pain in the ass. Compared to iTunes and Netflix, piracy in general is a pain the ass. But piracy is often less a pain in the ass than almost every other form of legitimate entertainment purchase. To wit: I don’t think I know anyone who still buys DVDs, simply because they’re so encumbered with bullshit, restrictions, ads and threats that it’s just not worth the bother.

Apple, Netflix, and Y Combinator have figured it out, this is very obvious. The MPAA and entertainment industry, they have not. Here’s hoping one subsumes the other, and quickly.

When a man’s paycheck depends on his not understanding something, you can depend upon his not understanding it. - Upton Sinclair

Blocking Facebook

While I do have a Facebook account (because it’s damned near impossible to delete one; it certainly isn’t possible via the Facebook site itself), for the most part I try to run invisible to Facebook. This is not as easy as it seems so below is my process for doing so.

I make no claims that this is bulletproof; if you have better suggestions, please share.

First, I installed the FacebookBlocker blocker browser extension. It seems to work well.

Then I installed the Ghostery browser plugin. Where FacebookBlocker is a scalpel, Ghostery is a big, heavy club… and every website is a juicy watermelon. I like Ghostery.

Perhaps most dramatically I’ve added the following to my /etc/hosts file:

# Kill all the facebook
127.0.0.1 static.ak.fbcdn.net
127.0.0.1 www.facebook.com
127.0.0.1 facebook.com
127.0.0.1 www.static.ak.fbcdn.net
127.0.0.1 login.facebook.com
127.0.0.1 www.login.facebook.com
127.0.0.1 fbcdn.net
127.0.0.1 www.fbcdn.net
127.0.0.1 fbcdn.com
127.0.0.1 www.fbcdn.com
127.0.0.1 static.ak.connect.facebook.com
127.0.0.1 www.static.ak.connect.facebook.com
127.0.0.1 m.facebook.com
127.0.0.1 touch.facebook.com
127.0.0.1 connect.facebook.net
127.0.0.1 api-read.facebook.com

It effectively routes all HTTP calls to Facebook-owned domains that I’m aware of to localhost, which means Facebook content doesn’t even get loaded.

It has the added effect of making Facebook hard to get to for me, personally. If I want to browse Facebook via a browser on my laptop then I have to actively launch the terminal, comment out those lines, and then reload the site. That’s usually enough of a PITA to curb any incentive I might have had to go visit.

Finally, I’ve deleted Facebook’s apps off of all my devices except one. And it’s very slow on that one.

Net result: I go onto Facebook perhaps once a week and whenever I see the Facebook sharing icon on another website, it’s always one hosted locally to that site instead of being served from Facebook’s CDN.

MacRuby and Checking a Path Is a Directory

MacRuby is awesome, but some aspects are very much Obj-C with Ruby lipstick. One of these is the use of pointers being set by functions as secondary effects. In Ruby we would just return multiple return values. Obj-C can’t do this, so sometimes it assigns to pointers.

I just ran into this when trying to determine if a file path is a directory or file. The obj-c approach is to use:

1
NSFileManager#fileExistsAtPath:isDirectory

where isDirectory sets a pointer to YES or NO.

In MacRuby we might do the following (wrapped in a convenience function):

1
2
3
4
5
6
def directory?( path )
  bool = Pointer.new_with_type( 'B' )
  file_man = NSFileManager.new
  file_man.fileExistsAtPath( path, isDirectory:bool )
  bool[0]
end

Ta da.

Rails 3.1, Deprecation Warning, and Primary_key_name

We’ve spent the past couple days upgrading the Travergence site from Rails 3.0 to 3.1 and while it hasn’t been entirely smooth, it hasn’t been horrible either. Except for one issue:

1
DEPRECATION WARNING: primary_key_name is deprecated and will be removed from Rails 3.2 (use foreign_key instead).

This would cause recursion somewhere in the stack, eventually leading to:

1
SystemStackError (stack level too deep)

After much digging, googling, commenting-out of code, and swearing I finally figured out that it was rails3_acts_as_paranoid causing the issue. One more google led to this solution by Chris Hilton, which involves patching rails3_acts_as_paranoid to prevent circular aliasing.

Hopefully Gonçalo Silva will fix it in the official branch on Github. Until then you can either fork and patch it yourself or grab ours:

1
gem 'rails3_acts_as_paranoid', :git => 'git@github.com:travergence/rails3_acts_as_paranoid.git'

ActiveMerchant, Bogus Gateways, and Credit Cards

When working with ActiveMerchant’s BogusGateway, it wants very explicit credit card numbers for testing. But it doesn’t really want numbers, it wants strings.

If you’re seeing this error, as I was:

1
Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error

make sure that your 1 and 2 are not integers but rather are strings.

When you create your credit card instance, I highly recommend casting the number explicitly:

1
ActiveMerchant::Billing::CreditCard.new( :number => number.to_s, :verification_value => security_code.to_s

iOS Simulator and “Couldn’t Register” Error

As far as I can tell, if you get this error when trying to run your app in the iOS simulator:

1
2
Couldn't register com.greenpointware.Konk-iOS with the bootstrap server. Error: unknown error code.
This generally means that another instance of this process was already running or is hung in the debugger.

the only course of action is to restart your machine. I’m sure there’s a process hung in the background that’s preventing it from working, as this line from the internets seems to suggest:

1
kill -9 `ps ax | grep Simulator | grep -v grep | awk '{print $1}'`

but that didn’t work for me. Rebooting did.

Stubbing Geocode With FactoryGirl

Google doesn’t seem to like it when our geocoded models hammer their geocoding API during our test runs so we should stub out the geocoding call. To do so:

1
2
3
4
5
6
7
8
9
10
11
FactoryGirl.define do
  factory :place do
    name         { Randgen.name }
    kind         'city'
    timezone     'Mountain Time (US & Canada)'
    enabled      true

    after_build  { |place| place.stub!( :geocode ).and_return( [1,1] ) }
    after_create { |place| place.stub!( :geocode ).and_return( [1,1] ) }
  end
end

Measuring Slow Code in Objective-C

A note to myself, because I can never remember how to do this:

1
2
3
4
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
...operation here...
NSTimeInterval duration = [NSDate timeIntervalSinceReferenceDate] - start;
NSLog( @"%f", duration  );

UIViewController Calling loadView() Multiple Times

I don’t know if this is one of those things that everyone else doing iPhone development automatically knows and I don’t, or if it’s an obscure, esoteric gotcha. It certainly did kill a bunch of my time today.

Turns out that a subclass of UIViewController doesn’t create a default UIView when instantiated. I discovered that by watching my controller’s loadView method get called multiple times (a dozen in fact) before crashing when I tried to add an instance of UIButton to the non-existant base view.

It seems that adding this at the beginning of loadView is the solution:

1
2
3
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
self.view = view;
[view release];

After that everything was great and trying to add the button no longer crashed the app.

Living Code

Long, long ago I posted Better Range Intersection in Ruby, which was Dan’s improved solution to my solution for finding intersections across date ranges.

Two years and 3,100 pageviews later, Montgomery Kosma came across that post, found a bug in it, provided a solution and immediately improved it’s quality. I love it when that happens!