Apple's TV is the new Apple TV

This TechCrunch article, written by David McIntosh of Redux, insists that AirPlay is not the new Apple TV. However, it starts from a flawed assumption that Apple would need to license the technology to many TV manufacturers.

The only technology Apple has really cared to license is the dock connector, and that was specifically to get an accessory ecosystem going in order to sell more devices. Integrating with TVs isn’t going to sell more devices, because the users that would buy such a television already have a device. The only immediate incentive Apple has to license the technology is to collect a hefty licensing fee, but that doesn’t amount to much.

Let’s say that licensing fee is $100 per unit (which no TV manufacturer is going to pay, but let’s give Apple the benefit of the doubt). There were 250 million television shipments last year. That’s a maximum of $24 billion per year, and we know the per-unit fee and the share of TVs using the technology would be much smaller. And with TV shipments falling year over year, that number would decrease over time. For a company that does $13 billion a month in revenue, this is quickly becoming chump change.

Another indirect incentive for Apple to license AirPlay would be to increase revenue for iTunes content. But, iTunes was always a ploy to attract people to purchasing Apple devices, not vice-versa.

I’m still of the opinion that Apple’s going to build a TV of its own and sell it to the richest consumers who already are invested in Apple’s media ecosystem.

~s

Using NSPopover with NSStatusItem

Mac OS X Lion supports a new Cocoa object called NSPopover. This object acts a lot like the popover introduced in CocoaTouch on iPad. There are lots of places normal applications can use NSPopover naturally. I recently started working on a personal project that uses an NSStatusItem, and wanted to use an NSPopover to manage the primary user interface for the content shown when interacting with the NSStatusItem.

Unfortunately, the interactions between a hidden object called NSPopoverWindow and Mac OS X’s NSStatusBarWindow create some problems. On top of this, having an NSPopover where the content view contains edit fields creates further problems.

However, I was finally able to get the interactions working correctly (at the expense of using the built-in NSPopoverBehavior styles). This post takes you through the problems and describes my solutions.

Yes, I could have used the Popup project, but I just wanted to make NSPopover work.

Initial Code

The initial code is pretty simple: just create a custom view and attach it to an NSStatusItem object. Even though I did not need more than the functionality provided by the default NSStatusItem object, NSPopover requires a view for the showRelativeToRect:ofView:preferredEdge: selector. I couldn’t figure out a way to access the _fView member of the NSStatusItem that’s visible in the debugger, so I was stuck re-implementing the basic NSStatusItem view functionality of an image that flips when activated. I call this BRStatusItemIconView. The code in the application delegate looks like this:

NSStatusItem* statusItem = [[NSStatusBar systemStatusBar]
  statusItemWithLength:32];
[statusItem setHighlightMode:YES];

_iconView = [[BRStatusItemIconView alloc]
  initWithStatusItem:statusItem];
_iconView.image = [NSImage imageNamed:@"Status"];
_iconView.highlightedImage = [NSImage imageNamed:@"StatusHighlighted"];

The initWithStatusItem: selector creates the necessary subviews (since it’s not loaded from a nib) and attaches itself to statusItem through setView:.

I used a separate object to be the popover controller and attach itself to the NSStatusItem. Since I used a custom view, the action and target properties of the NSStatusItem couldn’t be used. I created a BRStatusItemIconViewDelegate protocol that had one selector:

- (void)activated:(BRStatusItemIconView*)sender;

When the icon was clicked, it would invoke this selector on a delegate. My BRStatusItemPopoverController object is the popover’s controller and attaches itself to the BRStatusIconView created in the application delegate. The popover was initialized like this:

_popover = [[NSPopover alloc] init];
_popover.behavior = NSPopoverBehaviorApplicationDefined;
_popover.contentViewController = viewController;
_popover.delegate = self;
_popover.animates = NO;

Note I used NSPopoverBehaviorApplicationDefined, the importance of which will be discussed later. The viewController here was a controller for a complex view that includes an edit field, which is also important to note.

So, now all I needed was to open and close the NSPopover! The simple version of the code in BRStatusItemPopoverController looked like this:

- (void)close {
  [_popover close];
  _shown = NO;
}

- (void)open {
  BRStatusItemIconView* view = _statusItem.view;
  [_popover showRelativeToRect:view.bounds ofView:view
    preferredEdge:NSMaxYEdge];
  _shown = YES;
}

- (void)activated:(BRStatusItemIconView*)sender {
  if (_shown) {
    [self close];
  } else {
    [self open];
  }
}

Hit run to try it out, and… it works! However, if the popover’s content view contained an NSTextField, you’d find that the field refuses to become first responder! Even making sure the field was marked editable in Interface Builder didn’t help. #FAIL.

Fixing Edit Fields

According to this StackOverflow question, the problem with the NSTextField is the parent window’s inability to become the key window. The answer in that question is to write a global category for your application:

NSWindow+canBecomeKeyWindow.h
@interface NSWindow (canBecomeKeyWindow)

@end

NSWindow+canBecomeKeyWindow.m
@implementation NSWindow (canBecomeKeyWindow)

//This is to fix a bug with 10.7 where an NSPopover with a text field
//cannot be edited if its parent window won't become key
//The pragma statements disable the corresponding warning for
//overriding an already-implemented method
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (BOOL)canBecomeKeyWindow
{
    return YES;
}
#pragma clang diagnostic pop

@end

Trying this out appears to work when you click the status item. You can click the NSTextField and it becomes editable! But, this has created a subtle problem: the status item only works correctly if the application that owns it is active. When inactive, the status item weirdly requires a double click to activate it, and even then, the double click sends two mouseDown: events to BRStatusItemIconView, causing the interaction to be out of phase with the user’s intention.

Fixing the double click

Long story short, we need to control when the NSStatusBarWindow window, the parent of BRStatusItemIconView, is allowed to become key. When the popover is opened, we want that to happen so that the popover’s content view can become first responder. When the popover is closed, we want to go back to the original behavior so that input to BRStatusItemIconView doesn’t get blocked. But, we aren’t familiar with the original behavior because it’s hidden by the original implementation of canBecomeKeyWindow:. Using a technique called method swizzling that helps us do this. Note that there is an updated version of method swizzling discussed here, but I’ve not implemented it in my code yet. The new code looks like this:

#import "NSWindow_canBecomeKeyWindow.h"
#include

BOOL shouldBecomeKeyWindow;
NSWindow* windowToOverride;

@implementation NSWindow (canBecomeKeyWindow)

//This is to fix a bug with 10.7 where an NSPopover with a text field
//cannot be edited if its parent window won't become key
//The pragma statements disable the corresponding warning for
//overriding an already-implemented method
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (BOOL)popoverCanBecomeKeyWindow
{
    if (self == windowToOverride) {
        return shouldBecomeKeyWindow;
    } else {
        return [self popoverCanBecomeKeyWindow];
    }
}

+ (void)load
{
    method_exchangeImplementations(
      class_getInstanceMethod(self, @selector(canBecomeKeyWindow)),
      class_getInstanceMethod(self, @selector(popoverCanBecomeKeyWindow)));
}
#pragma clang diagnostic pop

@end

Now, shouldBecomeKeyWindow and windowToOverride just need to be set correctly. As I said above, we want windowToOverride to be the NSStatusBarWindow and shouldBecomeKeyWindow to change based on the status of the popover being visible. The new BRStatusItemPopoverController code is this:

- (void)close
{
    [_popover close];
    shouldBecomeKeyWindow = NO;
    _shown = NO;
}

- (void)open
{
    BRStatusItemIconView* view = (BRStatusItemIconView*)_statusItem.view;

    shouldBecomeKeyWindow = YES;
    [_popover showRelativeToRect:view.bounds ofView:view
      preferredEdge:NSMaxYEdge];

    windowToOverride = view.window;
    [view.window becomeKeyWindow];
    _shown = YES;
}

Adding transient behavior

Finally! Things work as they should. However, one cool thing about NSPopover’s default functionality is its ability to be a transient presence for the user. For applications that use the status bar, this is good behavior. However, because NSPopoverBehaviorApplicationDefined was used, we have to duplicate that functionality. Basically, we want the popover to be able to disappear when the application resigns being active. This can be done by listening to the appropriate notifications in BRStatusItemPopoverController and changing the ability of the NSStatusBarWindow to become key, or close the popover.

- (void)applicationDidResignActive:(NSNotification*)n
{
    if ((self.behavior == BRStatusItemPopoverBehaviorTransient) &&
       _shown) {
        [self close];
    } else if (self.behavior == BRStatusItemPopoverBehaviorPermanent) {
        shouldBecomeKeyWindow = NO;
    }
}

Conclusion

Apple has some bugs to fix related to NSPopover and NSStatusBarWindow. It seems obvious to me that applications that live in the status bar should use NSPopover to present complex user interfaces, but the complexity of doing so right now is too high.

Apple's TV Playbook

I’ve written a number of times about television. When I wrote what I thought Apple TV should have been, I thought things like a CableCARD DVR and a DVD player would be key features for me to buy it. If I could be Apple in 2011 designing a TV, I think I’d do it this way:

Industrial Design

Televisions are known for black or grey bezels with various curves, markings, buttons, LEDs, grills (for speakers) and technology brandings. Some of these are functional, while others are meant to distinguish them from the competition. I would think Apple will either borrow from the glass & white plastic bezel of iOS devices, or borrow from the brushed aluminum motif of the Cinema Display. The bezel itself will be clean; there might be one LED on it to indicate it is on, though I doubt even that. I’m guessing there will only be a power button, because you won’t need to control the device at the TV itself. Apple won’t need any branding on the device other than its own logo, and I think the rest of the design will be so clean for a TV that people won’t mistake it for anything but the Apple TV if it didn’t have that either.

Photo Frame

It used to be that people adorned their walls at home with beautiful art. Then, the television came along and ruined everything: the center of attention became a garish box rather than a piece of art. Considering the industrial design of the TV itself is likely going to be quite nice, it seems it would go to waste if it was off all the time. I could see Apple extending their iPad photo frame functionality to the television, where it automatically starts showing content while it’s on but not playing anything. Alternatively, you could manually start it by holding/touching the power button.

Inputs & Outputs

I would put four connectors on this device: power, HDMI in, HDMI out, and a network adapter. Unfortunately, no one has invented wireless power that can supply the wattage a television needs, so that one has to be there. HDMI out is an easy one: if you’re a home theater nut, you’ll want to hear the audio through your speaker setup. The network adapter is understandable for the case where wifi isn’t available or has low signal quality. Finally, when it comes to HDMI in, my logic goes like this: either you are a simple consumer that has a cable box and perhaps a DVD player, or you are a home theater nut and you have lots of components and a receiver. If you’re the former category, Apple wants to replace at least one of those boxes. For these people, Apple might automatically switch to the HDMI in signal when it detects something is on. That way, if you want to use your cable box or DVD player, you only have to turn it on and not futz with some other mechanism. If you’re in the latter category, you’ll use the receiver to switch between inputs.

Apple might throw in an IR receiver just as a throw back to people who have the old Apple remote.

Remote Control

I mentioned that there wouldn’t be any buttons on the device if I were to design it. I believe Apple will place remote command and control on iOS devices. iPhone and iPod Touch users will get a simple experience for command and control. It depends on the content service that goes along with the device, but if they provide a cable-style service, I could see a simple electronic program guide primarily driven by search. iPad users will get a better experience: a natural electronic program guide due to the device’s larger screen.

AirPlay

More importantly, Apple will recognize that discovery and consumption lie in two different places. The TV display is great for consumption, but the human interface for discovery has always been poor, especially on archaic cable boxes. Many people think Siri will be an important part of Apple TV’s value proposition, but I’m not convinced of it. Rather, Apple already has a great, reconfigurable remote control in iOS devices. iOS 5’s ability to use AirPlay wirelessly will enable Apple to create a discovery experience that leverages the TV so that the family doesn’t have to huddle around an iPhone or iPad, but the primary interaction will take place on one of those devices.

Configuration

The only reason I could see Apple making the screen a touchscreen is for configuring its networking. However, I don’t think they will do that. This article sounds very prescient. Configuration over bluetooth from an iOS device would be understandable for so many people, it makes the most sense. Alternatively, for people who use wired ethernet instead, they’ll be able to use iTunes from their computer to perform the configuration and then disconnect the cable if they desire.

Content

I honestly have no idea what Apple is going to do with content. Everyone is expecting some amazing cable-style subscription service. I have to question whether that will happen because Apple couldn’t compete on price with cable companies since the media companies are not going to be fooled into giving Apple preferential deal terms. At least, I would think they wouldn’t.

~s

nest

In the three months that I have not written on this blog, HP killed webOS, Amazon became a real device maker, and Steve Jobs passed away. Technology really does move fast – I already have to eat my words regarding HP. I still think HP’s strategy held water, but it was Mark Hurd’s strategy and not in Leo Apothekar’s playbook.

The thing that got me excited enough to write something again was the announcement of nest labs' thermostat. Now that the edges of technology have pushed communication forward, it’s time that it helped the every day activities with which we are already familiar. nest is a great name because, to me, it obviously implies the grandiose nature of the company’s goals: to change the technologies used within our homes every day to be more efficient.

A direction I think nest will go in the future is fridges. 30% of food is wasted, and a good portion comes from fridges at home. Remember being promised a fridge that would know when food had gone bad and ordered more groceries? Seems like something that could be done in the future.

I’ve got high hopes for nest: The world needs people who are willing to bring design and usability to products that live in perpetual mediocrity. We can’t wait for Apple to get bored with media consumption to go start building smart lamps.

~s