Open Shelf…

Apple TV 2.0 Support 03Jul08 | 0

I’ve had a whole lot of emails from people asking me about AppleTV 2 support for ATVLoader and the BDK. As the notes at the top of those two product pages mention, the currently released versions are incompatible with Apple TV 2.0. In addition, the BDK requires Tiger, and will not run on Leopard out of the box.

For ATV Loader v2.0, I’m planning on updating the infrastructure such that more types of appliances can be installed. I’ll also be defining a proper package format such that developers can provide tailored installations for their products. There may be a new plugin site, I’m not sure of that yet, since other people have to be involved. But I’m certainly leaning that way at the moment.

Version 2 of the BDK will rely on Xcode 3.1 because it will use the same multi-platform support framework that the iPhone SDK uses. The Test Harness will be rewritten to be similar to the iPhone Simulator in execution, so there will be three platform-specific versions installed: one each for Leopard, AppleTV 1.1, and AppleTV 2.0. You will be able to choose a platform to build & test against from your Xcode windows as with the iPhone. Currently Xcode 3.1 is in beta, so this won’t be officially released until that comes out of beta. I would expect this to happen around July 11th, at which point I’ll be making sure everything I’ve got right now is compatible, and then going into a testing phase leading up to a release in early August. I’ll be using this myself, so it should get some good stress testing by then.

Stay tuned for more information.

BDK Update v1.1.1 03Aug07 | 0

A minor update to the BDK today: I’ve rebuilt the BackRow header package with the ones on my machine, since it would appear that the current release didn’t actually have the latest ones, and was missing some enumerations & such.

Download Installer Download it here

AppleTV Software 1.1, Loader and BDK Updated 21Jun07 | 3

So, yesterday AppleTV software version 1.1 dropped, along with YouTube support, which is nice. Also nice is a whole slew of new UI classes for appliance plugin developers. Mmmm.

Not so nice is the way that it changed a few APIs, moved some into a whole new framework, and deleted a vast amount of unnecessary OS X components. These components happen to include everything necessary to act as either a client or a server for most network file systems, amongst other things.

Ah well. I guess I’ll be writing a simple server system for the AppleTV then, to help people drop their media onto it. I might get that done this weekend, depending on any further fallout from the update.

For now, however, the BDK has been updated, as has the Loader appliance. The Loader should function on both versions of the AppleTV software, so an upgrade to version 1.1 isn’t absolutely required. The BDK, however, uses a number of the changed routines, so it is now dependant upon the latest version of the BackRow framework, and requires the AppleTV framework to be installed locally. It does include headers for the new BackRow framework, however.

For information on the changes in the BDK, you can look at its change log, and for information on making your plugins compatible with AppleTV version 1.1, you can look here.

The Xcode project template has been updated with the required plugin changes, so new projects will automatically be compatible with AppleTV 1.1. I’ve also provided some information on the update in the online help for the BDK testbed application.

Marching Icons 18Jun07 | 0

I’ve been asked about this by a few people now: how does the icon display on the Main Menu work, and can I use it in my plugin? Well, the answers are ‘reasonably easily’ and ‘yes’, and today’s tutorial will show you how to do it.

Sample code for this tutorial Download the sample code for this tutorial

Important Note:

The code in this tutorial was written for BackRow version 2.0. Now that Apple has released AppleTV software version 1.1, some changes need to be made. In the tutorial and in the sample code, you will need to replace the [[self list] selection] call with [[self list] renderSelection].

[…]

BDK Update: v1.0.1 03Jun07 | 0

The BackRow Developers’ Kit has been updated slightly. There was a bug in the keyboard handling support, where it would incorrectly post a button-up event for tap left & right, where it shouldn’t do so.

The new version is downloadable from the usual place.

Loading your own textures 02Jun07 | 0

This is something I’m asked about fairly frequently, and the answer is actually pretty simple; it involves about ten or fifteen lines of code, overall, and BackRow provides just about everything you’ll need.

[…]

The new BDK Introductory video 01Jun07 | 0

Because the original video was so darned big, I decided to re-record it at a lower resolution, and try to lower the file size a bit. So, we now have a slightly expanded tutorial which shows the implementation of a recursive menu system. This will hopefully show a little more of how the menu controllers work than the original version, too.

You can watch the video inline, but I’d recommend downloading it to be able to view it full-size (720×576, i.e. PAL 576p).

Update: The podcast feed is now available on the iTunes Music Store. Subscribe, rate, review and enjoy, people :)

[display_podcast]

A correction: CFBundleName vs. FRApplianceName 31May07 | 10

So, I’ve mentioned on a number of occasions that the non-localized ‘CFBundleName’ showing up in the main menu can be alleviated through developers adding an FRApplianceName key to their Info.plist. I even explicitly pointed this out on the huge video tutorial — which is being downsized by my good friend (and also my hosting provider, at RGHosting) as I type this, ready to become the start of a proper podcast.

However, there needs to be a little change to this information. It’s technically true, except for a little bug in the implementation, due I would guess to the addition of some layers above the NSBundle API used to fetch the localized string value.

The code used by the BRApplianceManager looks something like this:

locName = [BRLocalizedStringManager localizedStringForKey: @"CFBundleName"
           inFile: @"InfoPlist" fromBundle: bundle];
if ( locName != nil )
    [dict setObject: locName forKey: @"FRApplianceName"];

The call into BRLocalizedStringManager on the first line can be effectively replaced with the following:

[NSBundle localizedStringForKey: @"CFBundleName"
                         inFile: @"InfoPlist" 
                     fromBundle: bundle];

…which is in turn the API underlying the NSLocalizedString functions. And you know what those routines do when you haven’t created your localizations yet? That’s right, they return the key.

So, we end up with some code which contains a fallback, but that fallback will never actually be used, because the function called never returns nil.

Oops.

So, I have to apologize for giving out what essentially amounted to misinformation there. Hopefully when Apple delivers the YouTube plugin they can fix this bug too, so we can have a working locale-independent fallback for the plugin name.

While we’re at it, why not make it fall back on the plain ‘CFBundleName’ property?

shrug

Nice bug you got there 30May07 | 0

So, iTunes 7.2 came out today, and along with it a lovely bug that’s crashing not only everyone’s Apple TVs, but also the BDK application. Well doh.

It seems that the iTunes Music Store is returning an invalid property list to the BRMusicStore class in BackRow, which is therefore throwing an exception parsing it, which goes to the Finder’s uncaught exception handler, which tries to allocate a BRPostedAlertController, which crashes the Finder. It actually looks like a weird issue I’ve seen where occasionally the toll-free bridging gets confused between a CFTypeRef and an NSObject, and tries to use objc_msgSend() for what is actually a CFTypeRef.

Here’s the exception details:


May 30 19:48:06 AppleTV FrontRow[926]: *** NSEXCEPTION RAISED ***
NSParseErrorException: XML parser error:
Encountered non-empty  tag on line 1
Old-style plist parser error:
Malformed data byte group at line 1; uneven length

0x9258f166: -[NSString(NSExtendedStringPropertyListParsing) propertyList] (in Foundation)
0x9e95e230: -[BRMusicStore(Private) _seedMusicStore] (in BackRow)
0x924ef2a8: forkThreadForFunction (in Foundation)
0x900243e7: _pthread_body (in libSystem.B.dylib)

And here’s a crash log.

So, the Word Of The Day? “DOH!”

Implementing an ‘About’ page 29May07 | 0

I was asked just now to explain how the ‘About’ page in ATV Loader works, and since it’s actually really simple, I thought I’d share it here.

It actually uses BRDocumentController, which can display any of the following components:

  • Title header, with or without an icon
  • Scrollable text (actually a BRParagraphTextControl)
  • A button, with a target & action

You can create your About.txt file in TextEdit in plain text mode (or your favourite plain-text editor), but be sure to save it using UTF-16 format. That last bit is important, because that’s what BRParagraphTextControl expects by default, although you can provide a different encoding by calling -setDocumentPath:encoding: instead of -setDocumentPath: as I do in the following example. I prefer UTF-16 though, since that means it’s fully localizable (you’ll never need to worry that under a different locale you’ll need a different encoding, at run time).

To use BRDocumentController, you call your choice of the header, document, and button setup methods, and finally call -doLayout to arrange your chosen items prior to display. This last is also important — without that, everything will be positioned at the lower-left, on top of one another. Any setup functions you don’t call will not create that object, so, as in the example below, not calling -setButtonTitle:action:target: will result in no button being created or displayed.

Here’s the code I use in ATV Loader, tweaked slightly to inline a separate method:


- (BRLayerController *) _showAbout
{
    // 'About' file path
    NSBundle * bundle = [NSBundle bundleForClass: [self class]];
    NSString * path = [bundle pathForResource: @"About" ofType: @"txt"];
    if ( path == nil )
        return ( nil );

    BRDocumentController * result = [[BRDocumentController alloc]
                                     initWithScene: [self scene]];

    // by default uses Unicode (UTF-16), which is what we used when
    // creating the file
    [result setDocumentPath: path];

    [result setHeaderTitle:
        BRLocalizedString(@"About ATVLoader", @"'About' document header")];
    [result setHeaderIcon: [self listIcon]
         horizontalOffset: [self listIconHorizontalOffset]
            kerningFactor: [self listIconKerningFactor]];

    [result doLayout];

    return ( [result autorelease] );
}