Ripe for Domination: The Mac Twitter Client Market

I remember my excitement when Tweetie for Mac was released. On the Mac my Twitter client of choice was the website itself. I used Tweetie on the iPhone, but none of the available Mac clients matched my mental model of what a Twitter client should be. Tweetie for iPhone however was a perfect match. So when Tweetie for Mac became available and I saw that it had the same organization and similarly excellent visual treatments as Tweetie for iPhone, I wasted no time in purchasing my license.

Since its release Tweetie for Mac has become the dominant native Mac client, but the product has not aged well. Updates have been rare and largely focused on bug fixes (thankfully there have at least been those). But indications of the future growth of Tweetie for Mac have been even rarer still.

For me personally what has been most aggravating about Tweetie for Mac over time is its unflinching un-Mac-like-ness in the timeline. Have you ever tried to drag a URL from a tweet into Safari? Or use Snow Leopard’s new Services features to process text? Or get the definition of the word the mouse pointer is hovering over using Ctrl-Cmd-D? Tweetie for Mac draws its tweets as custom views and because of this implementation decision the user can’t take advantage of all of these great built-in features of Cocoa’s text system that are found in almost every application in the system — features that are a big part of what make Macs great. Instead, the users rely on the developer emulating these features as he has done (so far) with only text selection and URL-clicking. I appreciate the effort but emulating the correct behavior will forever be playing catch-up with the system controls.

Common keyboard shortcuts such as Fn-Up/Down Arrow (page up, page down) for navigation are missing as well — another conspicuous inconsistency. Perhaps you can see why the fact that Tweetie for Mac won the 2010 Ars Design Award for “Best Mac OS X User Experience” has mystified me.


Hibari 1.0, a new Mac Twitter client, was released today with various high profile links to it. It has a gorgeous website and attractive screenshots. As you can imagine I was excited to take it for a spin. After all, it has some great features: mute (a sort of silent unfollow), keyword block/filtering, individual tweet hiding and in-timeline conversation expansion.

While I am happy to find that Hibari 1.0′s timeline works just as a Mac user would expect with URL dragging, text services, and so forth, what’s puzzling about it is what it doesn’t offer:

  • You can’t use Hibari to follow new people or unfollow the tedious (@HibariApp was kind enough to respond to my question on this, explaining that they didn’t want to make the context menu any larger).
  • Clicking on any @name opens the user’s Twitter page in your web browser, which is very jarring if you’re accustomed to Tweetie for Mac’s ability to view any user’s tweets without switching apps. An unfortunate side effect of this is that you can only use the in-timeline conversation expansion on your own conversations; if you want to jump into another conversation you’re on your own.
  • Most frustrating, Hibari doesn’t hold your position in the scroll view as new tweets appear. Instead it always shows the most recent tweets in your timeline. (Update: @HibariApp informs us that this is on the way.)

Initially I was very put off that these features were missing. After all, it’s Hibari 1.0. Not 0.9, not Beta 3, but one-point-oh. Calling a product “1.0″ and accepting money for licenses signals to the customer that the product is Capital R Ready. You probably have a number of features sketched out for subsequent revisions, but you have presumably included all of the features you view as necessary to use the product. We can only assume that Hibari’s developer, Victoria Wang, did not view these features as necessary.

I qualified the sentence above with “Initially” because as I re-surveyed the top Twitter clients for Mac in writing this article, I realized how unique portions of Tweetie for Mac are. Neither Hibari, Twitterific nor Bluebird (1.0 Beta 3) support viewing an arbitrary user’s tweets. None of them support managing your follow/unfollow status, either. They are focused only on viewing the contents of your timeline, your mentions, and your direct messages.

What I find most disappointing about Hibari is that it has made its 1.0 splash demonstrating some great new features, but it lacks features that Tweetie (and other iPhone clients) have made users like me consider standard. Standard to the point that we will continue using Tweetie (despite its significant flaws) and hopefully check in again on Hibari once it reaches 2.0. As much as I would like to see these features in Hibari sooner than later, I would rather they be designed with the same care that seems to have been taken with the rest of the application.


Today the Mac Twitter client market is Tweetie’s to lose. Hibari shows promise with its filtering preferences but set its sights below providing what I would describe as a complete Twitter client. The draw of Tweetie is not just that it provides a pleasant way to keep up-to-date on my Twitter timeline, but that it provides me with the way I like to consume Twitter best, end-to-end. This is the potential power any native Mac client, for any service. Tweetie has shown us what’s possible; its languishment has been and continues to be a talented developer’s golden opportunity.

Posted in Mac, Opinion | Tagged , , , | 1 Comment

Tip of the Hat

I saw (via Kottke) that Steve Carrell says he will be leaving The Office at the conclusion of the seventh season. As someone who was a fan of the original The Office (the British one, you know) and who was dismayed to learn that The Office was coming to NBC (Are there no good, original ideas for shows waiting to be made? Are we so devoid of creativity that we have to adapt every hit BBC show?), and who, after several years, came to have a certain level of respect for the new adaptation The Office, I am happy to read this news. Not that I had reason to suspect otherwise, but I’m glad somebody over here knows how to quit when you’re ahead.

Part of the charm of the original The Office, part of what made it special, was that it was comprised of two seasons, a wonderful “Christmas special” tying up some loose ends, and poof. The End. Very neat, very very good, and complete. When every indication is that content creators cannot let go of anything, that every property must be propped up again and again for milking (c.f. endless classic movie remakes, even prequels to long-thought-complete trilogies, etc.), it is refreshing to see a message that’s all too rare: My work here is done; it’s time for something new.

Posted in Opinion | Leave a comment

Fun with Blocks (in Objective-C)

I’ve been working on a Mac application recently that’s 10.6-targeted, which has afforded me a multitude of opportunities to use blocks (Apple’s C language extension introduced in Mac OS X 10.6) to get some tricky features written with a level of grace that previously wouldn’t have been possible.

If you’re a Mac or iOS developer and you’re wondering what good blocks are outside of NSOperationQueue/Grand Central Dispatch, or if you’d like to see some fun ways to take advantage of blocks, check out the most recent installment of Ask Big Nerd Ranch on using blocks in Objective-C, authored by yours truly.

BNRBlockView (gist) is my favorite of the bunch, and the NSThread additions are invaluable building blocks (pun not intended, void where prohibited).

Posted in Cocoa, Programming | Leave a comment

P-ROC in Gameroom Magazine

P-ROC in Gameroom Magazine We were at a friend’s house last weekend when he brought this Gameroom magazine article to my attention: a blurb about P-ROC, including an excerpt of the Pinball News article.

It’s nice to see the project getting a little press, particularly of the print periodical variety.

Posted in P-ROC | Leave a comment

NSBackgroundStyleRaised Rx

I was having quite a bit of trouble getting NSBackgroundStyleRaised to work on my NSView subclass’s label, creating the NSTextField programmatically. I tried fiddling with the background color, I tried disabling my drawRect:. Really hard.

The strange thing was that it was working on labels I had created in Interface Builder but was setting the background style on programmatically. I didn’t find the answer until I looked closely at the settings that Interface Builder makes on labels. Here’s the solution:

[textField setDrawsBackground:NO];

And now I have a label that looks great on its superview’s gradient background.

Posted in Programming | Tagged | Leave a comment

P-ROC/pyprocgame December Video Demo

Tonight I cut together some footage of the latest pyprocgame code (see my previous post on pyprocgame). The result is available on YouTube.

The music is lunar FREAK on by ast0r, who I found out about through Andy Baio’s amazing Kind of Bloop project.

Posted in Pinball, Projects | Tagged , , , , | 1 Comment

Introduction to pyprocgame

Gerry Stellenberg’s P-ROC became available today and I thought this would be a good time to write about the open source software that’s written to work with it. First, though, I want to talk about what P-ROC is and what makes it so cool.

What’s P-ROC (and Why)?

proc-plated-threequarter-160 P-ROC is a circuit board that allows you to control a pinball machine using software on your computer. It’s basically a big digital I/O board with an FPGA at the center that connects to your computer (Mac, Windows, Linux) over USB. P-ROC replaces the CPU board in your pinball machine (or, if you’re making one from scratch, is the CPU board, in a sense) and connects to the switch matrix, the driver board and the DMD itself to provide complete control.

Before P-ROC, if you wanted to create your own pinball game with your own rules, you had to either:

  • Learn to write assembly or rig up a C compiler to generate the requisite machine code and burn your own ROMs (essentially what the FreeWPC project is doing).
  • Write code in a custom high level language designed for use on pre-DMD era 80′s solid state pinball games (such as Ni-Wumph). Or,
  • Design your own architecture from scratch.

Frankly, none of those approaches sounded good to me. I don’t know enough about digital design (much less analog) to create my own hardware, I want to program DMD games, and I’m too big of a fan of higher level languages like Python and Ruby to want to spend all of my time worrying about managing code pages — plus it would be fun to have the option to fiddle with a functional language like Scheme or Erlang for pinball development.

Luckily for me, P-ROC fits the bill. You can imagine that I was pretty excited to find out about it several months ago. Having a few strong ideas about APIs and development tools, and coming from the perspective of someone who knew how he wanted to interact with this board, I made it my business to share my opinions on how the software should be organized. Several months later we have libpinproc, the C interface to P-ROC, and pyprocgame, a set of Python classes built on top of libpinproc that provides a very nice — if I do say so myself — framework for programming a pinball machine.

What pyprocgame Code Looks Like

Let’s just get right to some overly simplistic demo code:

class AttractMode(Mode):

  def sw_startButton_active(sw):
    self.game.coils.troughEject.pulse(20)
 
  def mode_started():
    self.game.lamps.startButton.schedule(schedule=0xff00ff00,
                                         cycle_seconds=0, now=False)

  def mode_stopped():
    self.game.lamps.startButton.disable()

You wouldn’t actually write code like this in a real game, but it demonstrates a few of the unique properties of pyprocgame:

  1. Mode class-based architecture. Essentially stackable state machines running in your game. A mode can be as simple as managing state for one shot, or as complex as an entire multiball mode. We leave it up to you.
  2. Easy handling of switch events. Define your switches in a common configuration file, then just add appropriately named methods to your Mode subclass. No need to define a constant, register a handler, etc. pyprocgame even makes more sophisticated switch events, like responding to a switch only after it has been in a certain state for a period of time, really simple: sw_startButton_inactive_for_500ms(sw):. pyprocgame handles the busywork of this kind of stuff for you.
  3. Easy access to game hardware elements like coils, lamps, and switches. The game-specific configuration file you load sets everything up.

The reason you wouldn’t write code like the above in a real game is that in reality modern pinball machines are pretty sophisticated systems. The trough eject call, for example, would likely be much more complicated in a real game (Is there a ball in the trough to eject? Is there already a ball in the shooter lane?). That’s why pyprocgame includes several generic mode classes to help out. Ball search and ball trough helpers, drop targets, service mode, DMD score displays, high score entry, and so on. We’ve also coded up a nice set of support classes for working with the DMD: fonts, animated layers, etc. There’s even great support for setting up your own lamp shows.

You can learn about the details of programming pinball machines with pyprocgame here: pyprocgame Overview. It’s a work in progress, but a lot is there already. And of course, also on GitHub, is the entire source of libpinproc and pyprocgame, as well as the code for the example Judge Dredd-based demonstration game.

What’s Next

It’s been a very rewarding project to work on with Gerry; now that the P-ROC board is available for purchase (and some are already shipping) I’m excited to see what people come up with. It’s been a thrill for me to see what he’s been able to build off of (and add onto) pyprocgame. If you’ll pardon my back-patting one last time, it’s really remarkable how quickly the framework enables you to add useful components to your game. I don’t want to imply that pyprocgame makes pinball development easy, but I think it’s probably the easiest solution out there that gives you the flexibility to do whatever kind of game you want to do.

A number of homebrew pinball hobbyists out there seem to be looking for something fully self-contained and not requiring a full computer. They may be turned off by P-ROC initially, but I think that this is still a great platform if that’s your goal. There are a number of reasonably priced single-board computers available now (such as BeagleBoard) that would probably make an excellent platform for running pyprocgame. Developing the software for a pinball machine is a big job (much less building one). I want to make it easy on myself during development and work on a desktop/laptop, then move to a more embedded platform when the project is ready for that.

Finally, I’m very interested to see if there are developers out there who have their own ideas about what a pinball development framework should look like. That’s why we provided the C libpinproc API: a basic toolkit that’s very close to the hardware, giving the framework developer a clean interface (without any assumptions) on which to build something bigger (and cooler).

I hope to post some video in a future installment (update: here); until then there’s this old drop target demo video.

Go check out the P-ROC site for more about the board, as well as forums.

Posted in Pinball, Programming | Tagged , , | 2 Comments

Driving a Pinball DMD with an Arduino Microcontroller

For quite some time now I’ve been interested in developing my own pinball machine. Obviously this is a massive endeavor. Before I happened across the P-ROC project, over the course of several days in April of 2007 I did some work on driving a pinball dot matrix display (DMD) with an Arduino microcontroller. Here’s what I made; read on for the details of how.

How It Works

Before we get too technical, a brief disclaimer: I am a computer scientist, not a digital design engineer. I’m self-taught when it comes to practical digital I/O knowledge, so some of my terminology may be a bit fuzzy. Also, and very importantly, I cannot take any responsibility for the crazy things you do to your pinball (or computer) hardware. You’re working with a high voltage peripheral here and while I seem to have escaped any ill results, you may not be so lucky. Be sure to ground the Arduino to the pinball machine ground, and keep your finger near the on/off switch. You may need to cut the power a few times before you get it right!

Let’s summarize what’s in the video:

  • A dot matrix display in a Shadow pinball machine. The game is powered up and running, but the DMD’s ribbon cable has been detached from the display controller board and is attached to…
  • An Arduino microcontroller, strapped to a solderless breadboard, and wired to the ribbon cable via the breadboard. I don’t recall exactly how it was wired up, but you can get an idea from the sketch source below. I do recall that there was at least a pull-down resistor on the Display Enable. This is important because if the DMD is left drawing the same row for a long time I suspect it will burn it in. (It shines extremely brightly in a rather bad sort of way.)
  • The Arduino is completely controlling the contents of the display (rudimentary pong in this case).
  • The Arduino is plugged into my Powerbook via USB for 5V power.
  • The DMD is powered by the pinball machine’s high voltage board. It would be possible to run this independent of the pinball machine if you had an appropriate DMD power supply.

As described in the PinWiki article on DMDs, the DMD is controlled by six digital I/O lines:

  • Display Enable
  • Row Data
  • Row Clock
  • Column Latch
  • Column Clock
  • Column Data

It’s essentially a serial interface (serial data via Row Data, clocked in with Row Clock), using the other I/Os to control the column position. The DMD works like a CRT. It has no onboard frame buffer; instead it has latches for one row’s worth of data. The Arduino must write these rows of data out constantly in order to maintain a picture. Here’s what the Arduino sketch I wrote does, in pseudocode:

for each row:
  for each 8 columns in this row:
    clock out dot data from bitmap at (column, row)
  latch in the row we just wrote
update bitmap
repeat

My initial implementation clocked out the dot data manually, but this ended up being much too slow. Thankfully the Arduino has a hardware SPI interface on pins 10-13 (although only the clock and data pins are needed). This allows you to rapidly clock out 8 bits of data with one call in Arduino C code (done by assigning to the SPDRvariable/register, in UpdateDMD() in the sample code). So the actual code is more like:

for each row:
  for each 8 columns in this row:
    write out those 8 columns all at once via SPI
  latch in the row we just wrote
update bitmap
repeat

You can see the source code for my Arduino sketch here: DMDTest.c. It’s very much a sketch; hopefully you can glean the important parts. Again, UpdateDMD() has the important stuff. I derived the background image with the UNIX banner program and a perl script to generate the bitmap array.

Conclusions

This project was a lot of fun to do, and very rewarding when I finally got it right. It took a lot of trial and error to get it working correctly. The question is, though, is this a practical means for driving your homebrew pinball machine’s display?

Frankly I suspect not. My experimentation showed that the Arduino I was using (ATMega 128, I believe) was just barely fast enough to do a reasonable job of keeping the picture bright enough and flicker-less. The DMD is very sensitive to the timing of its driver (the Arduino in this case), so it would prove very tricky (in my estimation) to a) drive the image consistently and b) do something else useful, like read any considerable amount of data off the serial lines (such as new frames), much less do something more involved like drive a lamp matrix, too. You may be much more of an embedded wizard than I am, however, and be able to figure it out.

There’s a very good reason that Williams et al had dedicated hardware to perform this function. Once I realized these limitations I began to imagine the ideal solution to be something like an FPGA driving the DMD off of some sort of shared memory setup. FPGA work is a bit beyond my skills at this point, so that was the end of the trail for me.

I did end up finding a solution that’s essentially done that, and more. It’s more expensive than an Arduino, but is a great fit for my interests (writing high level code on a PC to control a pin): P-ROC. Full disclosure: I have contributed a lot of open source software to this project in the form of pyprocgame and libpinproc. I hope to write a bit more about my work with P-ROC here in the future.

If you do end up implementing your own DMD controller, even on an Arduino, drop me a line about it!

Posted in Pinball, Projects | Tagged , , , | 3 Comments

Editing a UITableView: The Animated Insert Row

This post originally appeared on my Incomplete Labs blog on September 2nd, 2009.

iphone_contact_editing An iPhone app I’m working on has your traditional table view with an edit button in the upper right. I wanted an “Add New Item” row to appear at the bottom of the table once the edit button was tapped (think iPhone contact editor), but I couldn’t find a succinct description of how that’s done. Here’s how I did it.

If you start out with a new UITableViewController subclass, Apple’s template code for the UITableViewController sets us up with what we need to enable the edit button: (it’s commented out in -viewDidLoad)

self.navigationItem.rightBarButtonItem = self.editButtonItem;

If we uncomment this line the newfound edit button will animate our table into a listing of (apparently) deletable rows. What we need is a way to add a row to the end of the section that we want the user to be able to add to. Initially I tried doing this by checking for -isEditing inside -tableView:numberOfRowsInSection:, hoping that the table data would be automagically reloaded when Edit was tapped (it wasn’t):

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([tableView isEditing])
        return [items count] + 1;
    else
        return [items count];
}

I also added code to -tableView:cellForRowAtIndexPath: to provide the a cell label for the extra row (“Add an item”), also implementing -tableView:editingStyleForRowAtIndexPath: to return UITableViewCellEditingStyleInsert as appropriate. Those steps are important, but they weren’t enough. My data source and delegate weren’t being queried for the updated information and the table view wasn’t showing the new row when the edit button was pressed.

What we need is a way to tell the UITableView that there is a new row, and we need to tell it at the right time. I was tempted to look at setting up my own target/action on the Edit button, but since we’re subclassing UITableViewController the -setEditing:animated: method is a great place to do this. We can just override it in our own subclass, being sure to call the superclass’s implementation:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];

Then we call the table view’s -insertRowsAtIndexPaths:withRowAnimation: to tell the table view where the row is being added when we’re editing. There’s a complementary call, -deleteRowsAtIndexPaths:withRowAnimation:, which will work for when we aren’t editing any longer:

    NSArray *paths = [NSArray arrayWithObject:
                        [NSIndexPath indexPathForRow:1 inSection:0]];
    if (editing)
    {
        [[self tableView] insertRowsAtIndexPaths:paths
                                withRowAnimation:UITableViewRowAnimationTop];
    }
    else {
        [[self tableView] deleteRowsAtIndexPaths:paths
                                withRowAnimation:UITableViewRowAnimationTop];
    }
}

That’s about it. -insertRowsAtIndexPaths:withRowAnimation: and its complement are the key to getting the behavior we want, and we can use them in other scenarios to get smooth table view updates.

Posted in Programming | Tagged , , | 3 Comments

Making NSPoint/NSRect/NSSize Objects

This post originally appeared on my Incomplete Labs blog on January 9th, 2008.

In Objective-C the common NSPoint/NSRect/NSSize/etc. data types are implemented as structures. But what if you need to pass one as an id data type (an object), as I needed to do this while implementing undo for a Cocoa application? The solution is NSValue, which serves as a basic wrapping/container object for these structures:

NSPoint point = NSMakePoint(x, y);
NSValue *pointValue =
  [[[NSValue alloc] initWithBytes:&point
    objCType:@encode(NSPoint)] autorelease];
[undoManager registerUndoWithTarget:obj
  selector:@selector(setPositionObject:)
  object:pointValue];

A few extra steps, but it gets the job done.

Posted in Programming | Tagged | 1 Comment