In the past, K-3D encapsulated the logic for identifying file types within the plugins that could read/write those file types - for example, the TIFFBitmapImporter plugin included logic for identifying TIFF files. Similarly, logic that could identify a Python script was part of the Python script engine plugin. To see if a given plugin was capable of working with a given piece of data, you instantiated the plugin, passed it the data, and queried it to see if it could work with the data. If the answer was yes, you could then call the appropriate plugin methods it and would "just work". While obvious to describe and execute, there were significant problems with this design:
- If a plugin didn't exist or couldn't be loaded due to missing dependencies, the file type manipulated by that plugin couldn't be identified. This limited the feedback that could be provided by the user interface to some variation of "unknown file type".
- Because the plugins that manipulated files had to be instantiated in order to identify the files, their dependencies became part of the program working-set even if they didn't ultimately match the file type and never got used. This limited the value of On Demand Modules, since loading a file (such as a bitmap) triggered loading of every plugin (and every dependency) that could possibly load that file (including PNG, JPEG, TIFF, OpenEXR, etc).
Now, K-3D has moved file identification logic into separate plugins, called "MIME handlers". These plugins implement the k3d::imime_handler interface, which provides API for identifying the MIME type of a file (identified by filepath) or a string. This leads to a very flexible and efficient system for filetype identification:
- Because file-identification plugins don't have to link to the same libraries as file-manipulation plugins, they can be used to give better user feedback. For example, instead of displaying "Unknown scripting language" on a machine without Python installed, the user interface can still identify the fact that a script is written in Python, and provide useful feedback.
- Sophisticated platform-dependent file-identification strategies can be implemented. MIME handler plugins that do simple platform-independent string comparison on filename extensions can be supplemented by more sophisticated plugins on those platforms that support it. Currently, a Gnome MIME handler has been implemented that uses the MIME-Type database provided by the Gnome libraries. Ideally, additional handlers can be written to take advantage of KDE, MacOSX, and Win32 APIs in similar fashion.
- File-manipulation plugins no-longer have to be instantiated to detect file types. Thus, a user loading a PNG bitmap will only have the PNG loader in their working-set instead of every bitmap loader plugin.
The process of loading a file / executing a script now proceeds as follows:
- Call k3d::mime::type::lookup() to identify the MIME type of a file / string.
- Use k3d::plugin::factory::lookup() to discover plugins that can work with the given MIME type.
- From the list of compatible plugins, instantiate one to work with the given data.
- File manipulation plugins publish the MIME type(s) that they can work with using k3d:mime-type as a Plugin Metadata key.
- Since there may be multiple MIME handler plugins available on a given platform, handlers must publish the order in which they should be used, using k3d:load-order as a Plugin Metadata key. Handlers are queried in-order, so handlers with a lower order number have higher priority.
- Similarly, there may be more-than-one file reader/writer for a given MIME type - k3d:load-order is used in this case to give plugins with lower order number priority. For example, TIFFBitmapImporter should be preferred over ImageMagickBitmapImporter, since it will likely provide more specific functionality.
- Since file access is now a two-step process (identify the MIME type, then identify the matching plugin), there may be additional work implementing file readers/writers. If a reader/writer is created for a file type that isn't identified by the current MIME handlers, authors may need to do one of two things:
- Update existing MIME handlers to identify the new file type. FileMagicMIMETypeHandler is the logical place for this.
- Create a new MIME handler that can identify the new file type. This option allows the plugin author to distribute their reader/writer without having to modify other handlers' sources.