One of the neat new features in iLife '09 is the "Learn to Play" feature in GarageBand. Unless, that is, you have a PowerPC Mac, because Apple says in its requirements for iLife '09 that

Learn to Play requires an Intel-based Mac with a dual-core processor or better.

And indeed, once I installed it on my Dual G5 PowerMac, I got a dialog that said

The Learn to Play feature requires an Intel-based Mac with a dual-core processor or better.

That's a shame, because that machine has been relegated to doing little else than doing GarageBand stuff, mostly because my MacBook Pro is powerful enough and has a large enough screen that there is rarely much need to go into our home office to do work-related things. But for Garageband, it's a fairly nice setup, with a Keystation 49e and an iControl. Moreover, using my MacBook Pro would be much more awkward -- especially since the monitor is old enough to have an ADC connector and won't plug into the laptop without an expensive adapter, so using GarageBand on it would feel much more awkward and cramped.

So I wondered whether this machine could be made to run Learn to Play. Even though it's about six years old, it's no slouch, so I figured it probably could, if only Apple would let it. Google is usually your friend for these kinds of things, but a few searches turned up nothing useful. If I waited, someone else might figure it out, but if I wanted it working today, I had to be that someone, and so I began to investigate.

I began by using lsbom on the Archive.bom file inside GarageBand_LTPContent.pkg (found in /Library/Receipts after installation), and things looked good, because this Learn-to-Play Content package was just the sound, video, and metadata for the provided first lessons, meaning that the Learn to Play code was in GarageBand proper. Again using the output of lsbom, this time on the content of GarageBand.pkg, combined with the file command, I found that all the compiled material had been compiled for both PowerPC and Intel.

So now all I had to do was change GarageBand's mind about the validity of the PowerPC platform. First, I monitored what files it accessed using OS X's opensnoop command. The opensnoop command gives you output that looks like

  UID    PID COMM          FD PATH                 
  501   3678 GarageBand    18 /dev/urandom         
  501   3678 GarageBand    18 /var/tmp/etilqs_U4un5wbhzMrpkXI 
  501   3678 GarageBand    16 /.vol/234881056/121855 

which is nice, but as you can see, sometimes file access goes through Carbon functions (such as FSOpenIterator), even if you're writing an entirely Objective-C based application, and Carbon loves to go through /.vol. So, just in case one of those files was of interest, I ran the output through the following one-liner as a filter

perl -pe 'use Mac::Files; s{(/\.vol/\d+/\d+)}{ResolveAlias(NewAliasMinimal $1)}eg'

(I actually added some caching in my original one-liner, but I've omitted it here for clarity). There may have been a single function I could have called to do the job, but as someone who tries to stay away from Carbon, good enough is good enough.

From this output, I discovered that when GarageBand gives you the error message, it's actually rendering an HTML page, coming from store_requirements.html inside the application bundle. I then decided that I should really be using Instruments to look at what was going on, and from looking at a file trace there, I found that the stack content at the time of the call looked like

 1. -[MAStore showErrorPageForURL:errorPageTemplate:webView:]
 2. -[DfNewProjectDialogController _selectCategoryForID:]
 3. __NSFireDelayedPerform
 4. CFRunLoopRunSpecific
 5. RunCurrentEventLoopInMode
 6. ReceiveNextEventCommon
 7. BlockUntilNextEventMatchingListInMode
 8. _DPSNextEvent
 9. -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
10. -[NSApplication run]
11. NSApplicationMain
12. main

Running GarageBand from within gdb showed that DfNewProjectDialogController's _selectCategoryForID: method was the one to look at, but it's a long function, and in gdb, you just see a lot of calls to objc_msgSend_rtp and objc_msgSend. A little digging with Google took me to this page on Dave Dribin's blog, where he recounts discovering Technical Note TN2124: Max OS X Debugging Magic which has a lot of useful tips, but most particularly

If you set the NSObjCMessageLoggingEnabled environment variable to YES, the Objective-C runtime will log all dispatched Objective-C messages to a file named /tmp/msgSends-<pid>.

Cool. I thus got a 250 MB file logging every method call as GarageBand ran. From that, the key part was

- DfPreferences DfPreferences doesMentorMeetsMinimalSystemRequirements
+ ECHardwareUtilities ECHardwareUtilities sharedHardwareUtilities
+ ECHardwareUtilities NSObject class
+ ECHardwareUtilities ECSingleton sharedInstance
+ ECHardwareUtilities NSObject class
+ ECHardwareUtilities ECHardwareUtilities singleton
+ ECHardwareUtilities ECHardwareUtilities singleton
- ECHardwareUtilities ECHardwareUtilities cpuType

When I saw that, I smiled. When GarageBand wonders doesMentorMeetsMinimalSystemRequirements, we just have help it come to the right conclusion. To make GarageBand happy with a PowerPC, we just need to put the following in a file, such as ppc-gb.gdb:

break doesMentorMeetsMinimalSystemRequirements
commands 1
  return 1
  continue
end

and then run

gdb -x ppc-gb.gdb /Applications/GarageBand.app/Contents/MacOS/GarageBand

(Update: And then you type run into gdb to actually start it up, and type quit when you're done, or run again to restart it.) It's possible to pretty this up a bit, and no doubt someone else will if they read this entry, but for me, objective achieved.

Ha!

And yes, it does run fine on a dual 2 GHz PowerPC G5, at least for the first Piano lesson. (I have the next two downloading as I write this.) Your mileage may vary, of course.

(Note to Apple, please don't break this. Note to other people, don't scream from the rooftops about how Apple sucks because you need to have this hack, because if you scream too loud, you may end up with a GarageBand that can't be hacked like this, or developers may end up with crippled tools, and these tools are very useful in lots of other situations besides this one.)

Update (Feb 4, 2009): GarageBand 5.0.1 came out today, and everything still seems to work. I can also report that the other piano lessons I downloaded (up to lesson four) also seem to work just fine.

Update (April 19, 2010): GarageBand 5.1, which actually came out about six months ago seems to remedy the problem I addressed with this article. Now it says “An Intel-based Mac computer is required for GarageBand Learn to Play.”, but continues in smaller text saying “You can use GarageBand Learn to Play on this Power-PC-based Mac, but you might experience inconsistent performance.” In other words, they do what they should have always done. Cool.