Report-an-Apple-Bug Friday for August 26, 2005

It’s the favorite day of the week for Apple developers worldwide!

We have reports from Brent Simmons and renowned drunkenbatman (and he’s got a pretty good one too). More bugs from Chris Woods, Mike Zornek. I’ll try to add more links to this entry as bugs are posted, but it’s a bit hard to track them at the moment (someone should make a website to track those).

In any case, I was supposed to write about a QTKit bug or limitation having to do with opening movies embedded inside files at a particular known offset. After several hours of work, I can say with relative confidence that QuickTime is one awesomely weird piece of technology. For reasons that are beyond my understanding, trying to open a perfectly valid movie file using a data fork reference number and NewMovieFromProperties fails with a movie not found error (-2048). Creating a movie for the same file using a POSIX path or a CFURL works perfectly fine. Of course, since QTKit doesn’t expose functionality equivalent to kQTDataLocationPropertyID_DataFork, there is no such equivalent problem in QTKit.

Which brings me to the code I posted in On Report-an-Apple-Bug Fridays and to my current state of confusion. The snippet I posted is part of MHKKit, a Foundation-based framework I am currently developing as part of the Riven X project, a Mac OS X native re-implementation of the popular game by Cyan Worlds. Riven data files contain several embedded QuickTime movies, and the only API that properly opens them is NewMovieFromProperties with kQTDataLocationPropertyID_DataFork and kQTMovieResourceLocatorPropertyID_FileOffset (which, incidentally, only works with kQTDataLocationPropertyID_DataFork). Pretty cute, isn’t it? But I get the message Apple, I won’t try to see logic in QuickTime anymore. I promise.

I still have a bug to post

But I still have a bug to post, although I’m almost certain it will finish as a duplicate because it’s such an obvious one. It involves the Dock and Uniform Type Identifiers. The theory is that UTIs are as of Tiger the primary way to determine the type of a items on the system, be them files, filesystem objects or more abstract entities like contacts or calendar events. Everything else (OSTypes, extensions and MIME types) maps back to a UTI. Therefore, if one is write a Tiger-only application, one should normally use UTIs for purposes of file type identification. If you’re not familiar with UTIs, I encourage you to read the link above which explains in good details what they are about. The executive summary is that they are a most worthy successor to every other type identification mechanism we’ve had so far.

One area in particular where UTIs should be used is in the Info.plist file that can be found in every bundle when it’s time to declare the types of documents or entities a particular application supports. This is the well-known CFBundleDocumentTypes key in plists. Instead of using CFBundleTypeExtensions or CFBundleTypeOSTypes, one should use LSItemContentTypes, which is specified as an array of UTIs corresponding to the document type entry it belongs to(CFBundleDocumentTypes is an array itself). Unfortunately, this isn’t quite usable yet because the Dock doesn’t perform conformance tests properly.

If you read the documentation about UTIs, you know they are organized in hierarchies. This implies some form of relationships between UTIs, which is called conformance. A UTI conforms to another UTI if it expresses a refinement of the conformed to type. A very simple example of conformance is with JPEG images. It’s readily apparent that a JPEG image is generally speaking an image, and thus the public.jpeg UTI conforms to the public.image UTI.

Conformance is really important and amazing because for example an image editing application doesn’t need to declare a document type for every known image format – all it needs to do is declare one document type with the UTI public.image and suddenly the system knows that particular application can open any image file.

We call a conformance test the process of computing whether a particular UTI conforms to another given UTI. For instance, a conformance test of public.jpeg and public.image would indicate public.jpegconforms to public.image. Similarly, a conformance test of public.mp3 and public.image would fail.

You can now most likely understand the bug when I say that the Dock doesn’t perform conformance tests properly. What happens is that if your application declares a document type with a UTI, say public.jpeg, the Dock will accept a file drop on that application’s icon only if the UTI of the file being dropped is exactly public.jpeg. If your document type uses public.image, the Dock will refuse the file drop. On the other hand, this works perfectly fine in the Finder.

Radar bug #4234661.

Not sure that QTKit wouldn’t work. Have you tried using -[QTMovie initWithAttributes:error:] and passing in a QTMovieFileNameAttribute and a QTMovieFileOffsetAttribute in the attributes dictionary? Doesn’t that work? If not, you should file a bug.

My bad; you are right, it’s a bug in QTKit. Should be easy to fix.