AppleTV for Mac

This remains the most popular thing I’ve ever posted — despite the fact that its really nothing special. The meat of it is a little start-up script that contains no undiscoverable tricks. I don’t even use it any more!
Nonetheless, it’s in-demand, and I can’t find a hosting method that can keep up. So, here’s my solution:

  • The start-up movie is no longer available here — it probably shouldn’t have been posted here to begin with. If you find someone with a Patchsticked AppleTV, it’s trivial to SCP in and grab the start-up movie (discussed here.)
    You can also use any other movie you want, which you specify when you edit the script.
  • The screen saver never worked right on a normal Mac, but Scott Q has engineered a replacement. His link appears to be down, but get in touch with him and send him your thanks.
  • The script itself is still available here.
    Copy and Paste the script into the AppleScript editor, updating it to provide the path to where ever you want your start-up video, and save it as a run-only script. Add it as a Login item in your account, and you’re set.
  • The background image I made is awful (it was just a screen shot) and I’m sure someone’s made better, but I’ll keep that here if you want it. If you do this right, you should only see the wallpaper for a few seconds anyway, so if you make yourself an all black image, or find a nice Apple logo, you’ll be all set.

And honestly, that’s all that was released. Like I said, nothing magical. My Mac Mini worked fine as a Home Theater PC, but eventually I just went with an actual hacked AppleTV (which smoothly handles anything but MKV) because I wanted my Mac for other things. If you find any other great ideas, feel free to share them here!

Assorted, Scattered Objective-C Notes as compared to C#

A outlet is like a pre-known property that can be bound
(ie: drag destination object to origin object and assign to the outlet (property) nextKeyView)
is like
[myObject methodToCall:parameters];
int i = myObject.assignValue;
is like
int i = [myObject assignValue];
is like
[[form window].makeKeyAndOrderFront:target];
object myObject();
is like
id myObject;
string myString;
is like
NSString *mystring;
Defining an instance method:
private string myMethod();
is like
– (NSString *)myMethod;
Defining a class method:
public DateTime myMethod();
is like
+ (NSDate *)myMethod;
private float convertAmountbyRate(float amt, float rate)
is like
– (float)convertAmount:(float)amt byRate:(float)rate;
convert.convertAmountbyRate(1.0, 2.3);
is like
[convert convertAmount:1.0 byRate 2.3];
public interface myInterface : myClass {…}
is like
@interface myInterface : NSObject {…} @end

Assorted, Scattered JavaScript Notes

Boolean(value) method returns false for falsey values, true for truthy values
falsy: false, null, undefined, “”, 0, NaN
truthy: everything else: “0”, “false”

+ as a leading operator converts a string to a number: +”42″ = 42. Same as Number(“42”) = 42), parseInt(“42”, 10) = 42
+”3″ + (+”4″) = 7

=== !== do not do type coercion, slightly faster

if (a) {
return a.member;
} else {
return a;
can be written as
return a && a.member;
if the first operand is truthy, return the second operand, else, return the first

but for || if the first operand is truthy, return the first operand, else, return the second:
var last = input || somethingElse;
so if input is truthy, then last is input, otherwise set last to somethingElse

you can label loops and break them by label:
myloop: for (whatever)
break myloop;

//other loop
for (var name in object) {
if (object.hasOwnProperty(name))        //avoids looking at objects we might have inherited from
name //is the current member
object[name] //is the current member value

//multiple conditions in switch statements
switch(something) {
case “;”;
case “,”;
case “.”;

//exceptions and object literals
throw new Error(myReason);

throw {         //create an “object literal” creates an exception object on the fly
name: myexceptionName,
message: reason

//object literals
an object literal is wrapped in { }
a name can be a names or a value
values are any type
: seperates names and values
, seperates pairs
object literals can be used anywhere a value can appear
var myObject = {name: “Jack”, ‘goto’: ‘Jail’, grade: ‘A’, level: 3};
var myName =;     //extracts “Jack”
var destination = myObject[‘goto’];     //extracts “Jail”
var destination = myObject[“name”];     //extracts “Jack”
var destination = myObject[goto];       //returns an error because goto is a reserved word, hence the other notation

//maker function
function maker (name, grade)
var it = {}; //makes a new empty object, good shorthand = name;
it.grade = grade;
return it;
var myObject = maker(“Jack”, “A”);

//an object with an object as a member, shorthanded
var myObject = {
name: “jack”,
grade: “a”,
clothes: {
pants: ‘blue’,
shirt: ‘red’

//if you have more than a couple parameters in a function, why not make them an object?
function myfunc(pa, pb, pc, pd, pe, pf)
myfunc(pa, pb, pc, pd, pe, pf)
function myfunc(specs)
myfunc({ pa: ‘1’, pc: ‘3’, pb:’2′, … })

** note: variables that are not var’ed become implicitly global

//specify object’s prototype on creation? linkage — doesn’t really exist
var newObject = object(otherObject);
//gives it a secret pointer to otherObject, but the secret pointer is used for retrieving only NOT storing
//object (lowercase) is a method that Yahoo made up
//different than

var newObject = Object() which equals: var newObject = object(Object.prototype)

delete myObject[memberName];    //deletes (sets to undefined) a member of an object

myArray[myArray.length] = 3     //appends to end of array (same as pop)

var myArray[]   //creates a new array?

Resolving missing dependencies when building a NeXTStep/OpenStep App

If you’ve played around with NextStep/OpenStep trying to build a sample app — say, so you can find out how much OS X/the iPhone is like those sweet black machines of yesteryear — you might have an error like this one, when attempting to build a sample app you’ve created: AppKit.h not found (or any one of the other billion header files that are missing)
This may mean an incomplete installation of the Developer tools. Here’s what to do:

  • From the Developer CD, open the NextCD folder and then Packages.
  • From the Services menu, use Open Sesame to open the Package as Root
  • Install the Package to its default file locations.

NextStep: Open as Root
Now, in your project in PB, you may need to tell the compiler where to find those libraries.

  • From the Tools menu, open the Inspector and look at the Build Attributes.
  • Under Framework Search Order, Set… a new path to where those files just got installed: /NextLibrary/Frameworks
  • Do the same for Header Search Order, but use /NextDeveloper/Headers

Project Builder: Framework Search
Now you should be able to Build in Project Builder! Note that PB doesn’t have a “Build and Go” that I can find, so once you build, you need to use Workspace Manager to find your newly made .app and double click it to test it out.

Automating an Apple TV with Cron

Copy and enable Cron from 10.4.
Schedule Cron jobs using crontab at the command line. Use Ctrl+D to exit crontab once all your jobs are created.
Restart the AppleTV at 8:10am every morning (say, to re-establish network connections with computers that were off during the night):
10 8 * * * sudo /sbin/reboot
Shutdown the AppleTV at 1:00am every morning:
0 1 * * * sudo /sbin/shutdown -h now
You’ll need to enable the frontrow account to use sudo without a password.

Hacking Time Machine

This past week I was the unfortunate victim of hard drive failure on my 1stgen Macbook Pro. After looking through my local NAS and finding that my most recent backup was done in April, I kicked myself a little bit. I have everything available to me to do regular backups, but like most people I am just too lazy. I decided that I wanted to try and get Time Machine to perform backups to a network share instead of a local drive. A simple terminal command was all that was needed to make my network volumes show up in Time Machine.
defaults write TMShowUnsupportedNetworkVolumes 1
Just changing this preference has worked for many other people, but I get the a message from Time Machine stating “The backup disk image could not be created.” Nothing on google or the apple support forums seems to give any good info on the situation.
Any ideas?

Bridging networks with WDS

WDS stands for wireless distribution system. The system was intended to allow a wireless network to span accross multiple access points without needing a wired backbone between them. This can be useful when you cannot physically connect the access points with a cable, but note that a hardwired backbone is preferred as WDS will cut your available wireless throughput in half. For more information on WDS check out wikipedia.
Editor’s note: If you can connect your two Linksys routers via a cable, check out this post for some tips.
My setup is using two Linksys WRT54G v2 routers running the third party Tomato firmware. My initial home network was setup using version 1.19 of the firmware and I haven’t seen any reasons to upgrade it right now. The new router that I am adding using WDS was recently bought at a swap meet for $10 and is running version 1.21 of the firmware. The reccomended setup for using WDS is available in the FAQ on the tomato website and is what I based my setup on.
Main router setup:
WAN: Setup as required by your ISP.
LAN: Pick an IP address ending in .1 for your router (usually and ensure the DHCP server is turned on.
Wireless Setup:

  • Wireless Setup: Access point + WDS (If you are only joining two wired networks you can set this to WDS only.)
  • SSID: [Pick one for your network.]
  • Channel: 3 (I tried using channel 10 first because that’s what my original wireless setup and was unable to get WDS to work. I also tried using channel 1 and couldn’t get that to work either.)
  • Wireless mode: Mixed. (I also tried using G only when I had the channel set to 1. This is supposed to work but I couldn’t get it to.)
  • Security: WPA Personal (WPA2 Personal will not work and neither will WPA / WPA2 Personal.)
  • Encryption: AES (I tried AES / TKIP and it would only work if it was only AES.)
  • Shared Key: [Pick one for your network]
  • WDS: Link with [MAC address of your 2nd router.] (There is also an option for Automatic / Lazy which I was not able to get to work.)

Second Router Setup:
WAN Setup: Disabled.
LAN Setup: Manually assign an IP to this router. Normally ending in .2 (Like Make sure that this IP address is not available to be assigned by DHCP from the main router.)
DHCP: Ensure that this is OFF!
Wireless Setup:

  • Wireless Setup: Access Point + WDS (This could also be only WDS if you want only one access point or if you are joining two wired networks together.)
  • SSID: [The same as the main router’s SSID]
  • Channel: 3 (Again this has to be the same as your other router.)
  • Wireless mode: Mixed.
  • Security: WPA Personal
  • Encryption: AES
  • Shared Key: [The same as your main router.]
  • WDS: Link with [MAC address of your main router.]

I also found that I had to enable STP in the Advanced > Routing options page. All other options were left at their default settings with the exception that I also have QoS setup in a manner similar to this post on the main router. You can check to see the status of whether or not your routers are communicating via WDS by looking at the Status > Device List page to see if you have a listing for WDS on both routers.
You an add as many additional routers as you would like by adding their MAC addresses to the “Link with” field of your wireless setup. You should avoid creating routing loops when adding additional routers and setup them up in a star, line, or tree topography. If you absolutely have to setup a ring topography for redundancy I recomend finding a way to join the routers together using a wired configuration and doing some research on STP and RIP.
Author’s Note: WDS is not officially part of any 802.11 standard and is not recognized by the Wifi Alliance. Many different products implement the feature differently and may be incompatible with other devices that also support WDS. The only way to be sure that your setup will work is to follow guides like this one of people who have tested known configurations. Your milage will vary. Good luck!