Overview of Generator Implementation

The Quick Look generator API gives you several approaches for implementing generators. This chapter describes what they are and suggests the approach most suitable for applications based on their document types. It also discusses thread safety and multithreading issues related to Quick Look generators.

This chapter summarizes only the generation of thumbnails and previews. See “Canceling Previews and Thumbnails” for a discussion of how to cancel the generation of thumbnails and previews.

The Quick Look Generator API

The header file QLGenerator.h in the Quick Look framework declares the programmatic interface for Quick Look generators. (Another header file, QLBase.h, is also in the Headers folder, but this file merely contains definitions of various macros used by both the Quick Look public and private interfaces.) The programmatic interface for generators is divided between thumbnail requests and preview requests, represented by opaque types QLThumbnailRequestRef and QLPreviewRequestRef, respectively. The API falls into three distinct categories:

An important distinction to keep in mind when programming generators is the difference between options and properties. Both are names of CFDictionaryRef parameters in Quick Look functions. But the options parameter in the callback functions GenerateThumbnailForURL and GeneratePreviewForURL is a dictionary of options, or hints, from the client to the generator for how the request should be handled. The properties parameter is the last parameter in the QLThumbnailRequest and QLPreviewRequest functions used for creating thumbnails and previews; the properties dictionary contains data supplemental to the created thumbnail or preview.

Approaches to Thumbnail and Preview Generation

The approach you take toward thumbnail and preview generation, and the Quick Look functions you use, depend on the kind of document your generator is intended for. Ask yourself these questions about the document:

Of course, whether the request is for a thumbnail or a preview enters into your choice of approach. If a request is for a thumbnail with a size no larger than a regular document icon, then a thumbnail at that size may be no better than the icon. If the request is for preview of a multipage document, do you show just the first page of the document or all of it? Whether the request is for a thumbnail or a preview, the performance of your generator is of paramount importance. For example, when a client requests thumbnails, it can request them for dozens of different documents; inefficient generators can make the client’s display of thumbnails appear sluggish. If the client requests a preview for a document that is over 200 pages, perhaps you should include only enough of the document for the user to identify it. For your generator you should adopt proper memory-management practices and the appropriate multithreading strategy. For more information about multithreaded generators and thread-safety issues, see “Generators and Thread Safety”

If you want to specify static thumbnail and preview images for a bundled document, you can take the easiest approach—it doesn’t even require a generator. Just have your application place the images inside the document bundle in a subfolder named QuickLook; the image file for thumbnails should be named Thumbnail.ext and the file for previews should be named Preview.ext (where ext is an extension such as tiff, png, or jpg). If you decide on this approach, you should not create a generator.

Programmatically, you can take one of the following approaches for generating your thumbnails and previews, depending on the document and other circumstances:

Generators and Thread Safety

For performance reasons, the Quick Look daemon (quicklookd) prefers to run a generator in its own thread, usually concurrently with other generators or even with the same generator when that generator is working on multiple documents. Given this, several thread-safety questions arise when you write code for a generator:

If you can determine the answer to these questions, you can configure your generator for optimum performance by setting the QLSupportsConcurrentRequests and QLNeedsToBeRunOnMainThread properties in you generator’s information property list (Info.plist). (If you are unsure of the answer to any of the above questions, assume the most conservative answer in terms of thread safety.) Table 4-1 summarizes the thread-safety status that Quick Look assumes when you assign different values to these two properties.

Table 4-1  Quick Look properties for specifying the thread-safety status of the generator

Quick Look property pair

Values

Thread-safety status

QLSupportsConcurrentRequests

QLNeedsToBeRunOnMainThread

NO

NO

Default. The generator code is not thread safe but it uses thread-safe frameworks. The generator is never called twice at the same time, but might be called on different threads.

QLSupportsConcurrentRequests

QLNeedsToBeRunOnMainThread

YES

NO

The generator code is thread safe and uses thread-safe frameworks. Quick Look can call the generator for several documents at the same time in different threads, including the main thread.

QLSupportsConcurrentRequests

QLNeedsToBeRunOnMainThread

NO

YES

The safest context, because Quick Look calls the generator serially in the main thread.

QLSupportsConcurrentRequests

QLNeedsToBeRunOnMainThread

YES

YES

In some situations, the Quick Look daemon may spin off a subprocess to handle requests from clients, so those requests might be dispatched to the same generator code in two different processes. This combination indicates that the generator is thread safe in that context.

For information about thread-safety issues, including the thread-safe status of the Carbon and Cocoa frameworks, see Threading Programming Guide.