Noooooooooo!
January 11th, 2006It looks like my dreams of replacing my Dell with a new MacBook are (temporarily?) shattered. [Via DaringFireball.net]
It looks like my dreams of replacing my Dell with a new MacBook are (temporarily?) shattered. [Via DaringFireball.net]
Now that Apple has announced the immediate availability of Intel-based Macintoshes, the developer community needs to get serious about adjusting our projects so that they build and run natively on the machines.
For a long time, Apple has made available the required SDK for “dry running” our projects as Intel-compatible builds. Some developers even took Apple up on the “transition kit” systems, which put Intel machines (though quite unlike the shipping units) in the hands of developers from a very early stage.
A common thread on the mailing lists seems to be the unhappy scenario of essentially having ones own code ported and ready to test, but being held hostage by the slowness of another library upon which you depend. When the library is open source, it’s easy enough to take responsibility for it yourself. Get your feet dirty and port the dang CurlHandle class over yourself! But many of us (perhaps unwisely) have gotten ourselves into situations where we depend upon the compiled code of others in our shipping products.
Kagi’s KRM module allows Kagi vendors to present users with an integrated purchasing dialog. It’s essentially a single dialog that takes the user’s financial information and ships it off to a Kagi server for further processing.
For those of us who have been using the Cocoa-specific version of KRM, the wait has been long for a universal version of the libraries. In fact, the wait will be very long. It doesn’t appear that Kagi is planning any further updates to the Cocoa-specific module. Instead, we’re offered the “Zonic KRM” module, which is a straight-C CarbonEvent based solution.
At first, I was annoyed by the presumption that Cocoa developers should have to pull up roots and switch to a new library with a new API (a straight-C one, to boot!). But after downloading and using the Zonic KRM solution, I am happy to report that it’s an overall cleaner and easier to use module than the previous Cocoa-based framework. As a single library archive and associated header file, this requires none of the linking and packaging headaches of the Cocoa KRM package. The API is straightforward and offers few opportunities for careless error. Even the UI is, ironically enough, improved over the Cocoa version.
The only major snag I’ve run into is that the Zonic purchase window doesn’t appear in the floating layer as the old Cocoa KRM did, and seems to suffer some activation issues when invoked from my LSUIElement application. These types of problems were what originally led me to choose Kagi over eSellerate, whose Carbon-based solution had the same problems. Hopefully these can be resolved with Kagi – I’ll have to investigate. [Ed. Note: These issues were more or less mistaken impressions, and are somewhat elaborated upon in updates at the end of this article]
All the improvements will mean little, however, to Carbophobic developers who have grown accustomed to avoiding most APIs that don’t fall firmly into the Cocoa space. I don’t blame them. If I didn’t already know this Carbon stuff, I probably wouldn’t want to sidetrack my rapidly progressing project to figure it out, either.
In the spirit of helping these developers out, and with the somewhat selfish goal of encouraging as many Intel-native apps as possible by the time my MacBook arrives, I’m posting a very simple demo project that shows how you might integrate the Zonic KRM modules into a Cocoa application. For this example, I’ve taken the attitude that you want your exposure to Carbon to be brief, handing back control to a “sane, Cocoa world” as soon as possible. The gist is pretty simple:
[Ed. Note: It has been pointed out that using the “modal” Zonic dialog is exceedingly simple, and doesn’t require any use of the Carbon event API.]
Note that since I’m not sure I have the right to redistribute the Zonic library and header file as-is, I’m not including them in the sample project. You’ll have to download them directly from Kagi.
I hope this proves helpful to some of you.
Update – My LSUIElement problems seem to be worked around by using the modal version of the Zonic dialog API.
Update 2 – Wed, 1/11/2006, 1:40PM EST. I’ve updated the sample project to include demo cases for both Modal and Modeless variants of the Zonic KRM dialog.
Update 3 – Wed, 1/11/2006, 1:55PM EST. Another update to the sample – should dispose of the Zonic result structure when done with it. Also, it should be noted that the “LSUIElement” related problems alluded to above are more general. It appears that Zonic KRM’s modeless dialog is not well suited to being displayed while a Cocoa NSPanel of any kind is being displayed.
Update 4 – Thursday, 1/12/2006, 1:55PM EST. Incorporate memory leak fix suggested by Kirk in the comments.
Update 5 – Friday, 1/13/2006, 10:48AM EST. Friday the 13th Special! Kagi and Zonic have kindly agreed to let me include the Zonic library and header file in the demo project, so it should be buildable as soon as you download it, presuming you have Xcode 2.2 installed.
Update 6 – Tuesday, 2/21/2006. I meant to point this out earlier, but forgot. There is a problem in the 1.0.4 Zonic release that causes it to crash on 10.2 deployments. An ingenious workaround was discovered by another Mac developer and shared with me via Kagi. Simply lipo the PowerPC code from Zonic 1.0.3 with the Intel code from 1.0.4. I’m using this solution in the interim and it gives a solid fix to the problem the Zonic 1.0.5 release is ready.
The other day as I walked home from the gym, listening to my iPod Nano, I started to feel jealous of the iPod Video owners. I love my Nano, but it would be cool to be able to watch video on it from time to time. In spite of having a pretty good color screen, I have no access to such a feature (except perhaps with some Linux-on-iPod trick).
Then I got a sick idea. What if I could convert the frames of a video into chapter markers in an iTunes AAC file?
You may be familiar with chapter markers: they allow authors of multi-part AAC audio files to put marker points in the file so that you can skip between different sections of the audio, even though it’s all part of one file. When you play a song or audio file on your iPod that includes these chapter markers, you can also see an associated image for each chapter.
So, I set out to create an AAC file with lots of chapters. Of course the mechanics of this are a bit harder than it sounds. I had to master Apple’s weird “ChapterTool” (the only official Apple software I know of distributed through a .Mac homepage!), came up with a funny perl script to generate the XML input file that ChapterTool requires, and relied heavily on a modified version of David Van Brink’s qt_tools and Pixture Studio’s awesome QuickImageCM.
I hacked on this for several hours today and finally came up with a pretty interesting demo (10MB). The linked file contains a 3.5 minute song with 800+ chapter markers. The result, as viewed in iTunes, is “somewhat video-like!™” I can’t figure out yet whether the slight jerkiness is because iTunes is not used to flipping chapter art so frequently, or because I screwed something up in the time code generation for the XML file.
Though the file behaves fairly well in iTunes, all hell breaks loose when I try to play the file on my Nano. The Nano sort of freezes for a minute before giving up and skipping to the next track. I guess Nano just isn’t ready to deal with that many chapters in a song file! I tried scaling back my experiment quite a bit by reducing the number of chapters to just one per second. While Nano is now able to play the song, it is rather flaky about keeping the displayed image up to date with the chapters as they fly by. Another major drawback to this “solution” is that having all those chapters on the song essentially makes it impossible to skip to the end or beginning of the track while it’s playing.
So while my dream of hacking video onto my Nano via iTunes is not exactly fulfilled, I think too much went into this not to share the (probably good) news of my failure.
Back in my first days at Apple, I was privileged to work with brilliant engineers (and a few idiots, lest I get too nostalgic). One of these brilliant types, who I might go so far as to describe as a mentor, had a mantra he’d throw out when anybody started whining about the difficulty of programming something. Without listening to the details, he’d sigh and give a contemptuous reply: “It’s only code!”
When I arrived at Apple I was one of the whiners. I thought there were at least three types of code in the world: easy, difficult, and magical. I thought of myself at that time as incredibly good at easy code, and perhaps squeaking by with some panache at the difficult stuff. The magical stuff – device drivers, etc. – I simply hoped nobody would ever ask me to do. By the time I left Apple, I had learned that my mentor was essentially correct.
In fact, his mantra was just a bit simplistic. There is easy code, and there is hard code. But there is no magical code. Furthermore, the ways in which people typically classify code into easy and hard categories is completely backwards. Most average programmers tend to think of things like device drivers and operating system scheduling as “hard,” while something like writing a word processing application is “easy.” In fact, the low-level code that most people are so afraid of is often the easiest code imaginable. It’s easy because it does so little. Device drivers often boil down to nothing more than a glorified switch statement – a slack-jawed servant carrying out with precision the demands of a device and its client. These are so easy even PhDs can write them! Of course, many low-level device drivers and services require elegance and brilliance to do well, but in many instances there is simply less need for clever programming at this level.
People confuse familiarity with ease. They don’t know what goes on beneath the surface of their OS’s GUI, so they assume whatever it is must be magic. If anything, these low-level services can be difficult to debug, but they’re often not difficult to code. I’m angering a lot of overpaid, sloppy device-driver engineers right now.
What’s really difficult is writing a word processor, or any other GUI application with a rich feature set and elegant UI mechanics. Writing a GUI application essentially requires defining a protocol for each “object” in the application, and writing “device drivers” that manage the interactions between those objects. So a program like Word is a web of thousands of device-driver like pieces of code, all interoperating without (we hope) knocking unexpectedly into each other. When this is done correctly, the user perceives it as magic. User magic is good!
But bad programmers assume that if it’s easy to use a program, it must also be easy to write the program. This is why we end up with a bazillion terrible “To Do List” type applications. Everybody thought it was easy, and yet even something with such relatively modest requirements far outweighs the difficulty factor of a relatively complex device driver.
So when good programmers come to me and foolishly describe themselves as unqualified for low-level work like OS design or hardware interfaces, I set them straight. You’re not unqualified – you might be overqualified! Now write me a kick-ass To Do List program.