Tuesday, September 23, 2008

How I Didn't Get Rich Via my iPhone App

I think we've all seen the stories about some guy in New Zealand making $6K a day for a Choplifter clone, or another fellow making $250K in two months reimagining Tetris. What you don't hear about are the flops. And I have a flop on my hands. My application to monitor over the air digital television signal quality, Signal GH has sold 10 copies. I had had no illusions that it would be a big seller; the target market is small at the intersection of iPhone owners and HDHomerun users; I just assumed there were a few thousand such people and they would all want my app.

Apparently not.

Unlike a lot of apps getting shoveled onto the App Store, Signal is competently coded; performs a useful service, launches quickly, doesn't leak, doesn't crash, and has only a smattering of bugs. Maybe prospective buyers would like to know this, but I have had no reviews so far.

Part of the problem was that Apple mistakenly lists its release date as the day I submitted it to them for testing, instead of the day they actually released it to the public, so I got no time on the front page of the Utilities page. And part is probably too high a price point, maybe $5 is just too much even for niche market apps. Again, I'm flying in the dark here because I've gotten zero feedback.

I also don't know where HDHomerun users hang out. The forums on Silicon Dust seem fairly low volume. Maybe if the HDHomerun were buggier, people would be filling their forums but dang it if the HDHomerun isn't the most reliable gadget on my network. And, I don't want to make commercial announcements on public forums anyway; nobody likes that sort of thing. I'm not a marketing wiz, I am a fairly good Mac coder.

Oh well, I only wasted a couple weeks of spare coding time. I've learned my lessons about targeting larger markets. I learned a thing or two about iPhone development, and hopefully my next post on the subject will be "How I Did Get Rich Via My iPhone App."

UPnP with Cocoa

Needing a license compatible implementation of UPnP I could use to locate MythTV frontends, I made the mistake of using the C++ version of CyberGarage's library. This was a mistake as the C++ version (1.7) is old and filled with bugs and leaks. The proper version to use is the C version (2.2) which is much less buggy and even comes with an Objective C wrapper class.

If you are writing an iPhone app and need to locate a UPnP device, this is probably the way to go.

Oh, and one thing to consider is that if you look through the code, you will see that the library avoids opening up connections with network interfaces that have the IFF_LOOPBACK flag set—for obvious reasons. You might want to also avoid network interfaces with the IFF_POINTOPOINT flag set, as that is as like as not the cell network radio, and you probably don't want to make UPnP inquiries over the cell network.

[Update: Looks like TCM Port Mapper might be the preferred library, but I haven't tried it.

Wednesday, September 10, 2008

iTunes 8 is still not Cocoa

Earlier in the year, I posted a blog entry about how Apple, obviously, must be getting ready to release a new version of iTunes based upon the Cocoa framework, and not the Carbon framework. While I still believe this to be true, iTunes 8 is not that product.

A quick look through the application's bundle shows all the signs of a product still deeply welded to Carbon.
A quick glance through the Info.plist:
  • No Principle Class so no NSApplication at launch
  • The HIWindowFlushAtFullRefreshRate flag is set indicating at least a few Carbon windows
  • Application requires Carbon environment flag is set

There are a few .nib files in the bundle, but all the ones I looked at were Carbon.

Localized strings are still kept in a resource (.rsrc) file! What in the world.

In fact, there are no obvious signs of any Cocoa use at all.

As someone who's day job involves maintaining a Carbon app that "should" be transitioned to Cocoa, I can sympathize. But it is concerning as Apple wastes development time adding features like Genius to a straight Carbon application. Anybody writing new features will know that their work will have a shelf life of about 9 months; and will have to be reimplemented—at least the GUI parts—in Cocoa. And the sooner a Cocoa iTunes comes out, the faster it will become a mature, bug-free product.

Thursday, September 04, 2008

Revamping a Dated Cocoa Application: InCDius 2.5

iPhone development has re-energized my love of programming. My day job requires me to do too much Win32 coding, and that is soul deadening for a Cocoa programmer. The combination of corporate priorities, and the fact I can add features much more quickly and with fewer bugs in Cocoa, leads me to spend a huge fraction of my time in Visual Studio, when I'd rather be in XCode. It's been draining.

I released InCDius 2 back in 2002, and it never got out of beta, although beta 16 was quite stable, and I apparently have a number of loyal (yet put upon) users. It is just an Audio CD database, not a personal media database like the well regarded Delicious Library. It was fast, and pretty darn stable, although a few users have had database corruption issues—please back up to XML people. I knew for years that I should release a new version, but could never quite muster the energy. It embarrassed me having this old, non-Intel application, gradually getting less stable with each OS release application; and I was considering my options for killing it entirely.

But my Remote Remote GH for iPhone application makes heavy use of the SQLite database, so I felt confident I could transition InCDius away from the Berkeley DB database. This transition had been the most daunting of the reasons keeping me from releasing an update.

My first impulse was to refactor the whole application using Core Data, but that would not have added anything but development time; the GUI was wired up quite well; the application was already scriptable. All I needed was a new database backend, and Apple ships OS X 10.5 with SQLite 3 right in /usr/lib. By choosing SQLite, I was no longer responsible for compiling and upgrading my database library; I can rely on it being there and just working. I tried using the QuickLite SQLite wrapper, but it was not capable for the task, as it creates a large number of objects maintaining its internal cache, to the point of locking up my Mac. No, I had to call the SQLite C API directly. As long as I minimize random access into the database, I get good results.

I also wanted this to be a release that could live on its own for a very long time; who knows how long I'll go without finding the time to update it. I wanted code which would last a very long time. This meant not only transitioning to Intel, but compiling for Intel 64-bit, and removing every deprecated API or framework message I could root out. I decided to make the minimum OS X version 10.5 (Leopard), and to transition the codebase to Objective C 2.0, although it isn't quite all there yet. I'll have to work on the garbage collection, but I am using both Objective C 2.0 fast enumeration loops and properties where appropriate.

Forward thinking means removing the past, so out went a few features tied to old APIs. I had been allowing users to import information from Classic Mac OS's CD Player preference file, but that involved using old school Resource Manager calls. Anybody ever going to use this feature again? No. Then out it goes, along with the Resource Manager.

I had 2 separate ways to play Audio CD tracks. One used QuickTime; one used Core Audio. Kept the Core Audio.

NSTableView has a new (to me) way to deal with selections with NSIndexSets, and deprecated the messages I had had been using. Goodbye old messages.

My own Objective C objects were filled with ints, unsigned ints, longs, and even the occasional unsigned. Hello NSInteger, NSUInteger and 64 bit computing.

I had been using a custom version of NSTableView to draw blue stripes. Goodbye custom class, hello check box in Interface Builder and grey stripes.

Obviously, I had been using .nib files for building my GUI. Time to upgrade everything to .xib files.

A user sent me his database (as a .zip archive of XML files) of 15,000 individual disks. Wow, and I had been thinking InCDius was zippy fast and ready for release. Massive performance tuning and the decision to load the database at runtime instead of upon the first search. Much simpler and reliable, and lets the user do something else while everything gets ready.

Take time to remove all the warning messages. You will save yourself a huge amount of hassle in programming, but especially in Cocoa programming if you eliminate all the compile warnings. You want to know right away if the compiler doesn't know if NSView responds to "releese". Do not let warnings build up. Fix them. Fix them all.

A Google Tech Talk by Linus Torvalds inspired me to change the unique identifier key I had been using to lookup disks in the database; he uses SHA1 hashes to avoid corruption in Git, and it seemed to me that a SHA1 hash of the Audio CD's Table of Contents would be as close as I could get to being unique; although there will be rare instances when 2 CDs cannot both be in the database.

So after all this, what do I have? A fast, reliable(?), clean, focused little application, which I can send out into the world; spend the next few months fixing the occasional bug and adding the occasional feature, and which people can use for a good long while.