Creating Spotlight Plugins
Pages: 1, 2, 3, 4
A Few Words on Debugging
Spotlight plugin development can be frustrating because the debugging process isn't always that easy. You have to actually install the plugin and monitor its behavior to determine if it's working, which means extra time copying files around, extra time on the command line, etc. Recall from last time the following tools
mdls: lists the metadata attributes for the specified filemdfind: finds files matching a given querymdimport: imports file hierarchies into the metadata datastoremdutil: manages the metadata stores used by Spotlight
Of these tools, stick mdimport inside of "code" tags to be absolutely vital. For example, mdimport -d1 ~/Library/StickiesData.aaa provides feedback that tells you whether or not the proper Spotlight plugin can be located by the server—a fair question to ask. Apple has a very good document on debugging Spotlight plugins available here that you should definitely read.
In Apple’s debugging document, you'll see references to a command called lsregister, which can force the Spotlight server to recognize a bundled Spotlight plugin (like the one just given to you in the "OpenStickies.app"). By default, however, this command is not in your path. Type the following into Terminal to place a soft link to lsregister in your path.
sudo ln -s /System/Library/Frameworks/ApplicationServices.framework/\
Versions/A/Frameworks/LaunchServices.framework/Versions/A/\
Support/lsregister /usr/bin/lsregister
A Freebie for All of your Hard Work
You may have already noticed an inconvenience. You can't click on the "StickiesDatabase.aaa" file that appears in Spotlight's results and have it open up Stickies, as would be the case for most any other application. This is truly annoying, but nothing a good old-fashioned hack can't fix.
By choosing to "Get Info" on a file, you can set its default application that should open it. The problem then is that there is no default application to do such a thing for type "aaa" files—well not yet. To get Stickies to come front and center when we click on the "StickiesDatabase.aaa" file in Spotlight's search window, we simply need to run a simple AppleScript from within an application bundle. The AppleScript is a one-liner:
tell application "Stickies" to activate
This script opens Stickies if it's not already open, and brings all of its windows to the front, giving us the desired effect even though it's not really "opening" the file at all. All that's left now is to create and associate a bundled utility application that executes the AppleScript with the ".aaa" file type. It's that simple.
Embedding an AppleScript into a Cocoa app is really simple, and you can read about it here. I've used this very approach to create a project called "OpenStickies.app." The project's source is available here.
One thing that I didn't mention is that you can embed Spotlight plugins into application bundles. If you'd like a compiled version of "OpenStickies.app" with the "StickiesImporter" plugin already embedded, you can get it here. You'll need copy it to your "Applications" folder and manually run it once to ensure it is "trusted." Once it's in place, go to your ~/Library/StickiesDatabase.aaa file (which cron should be updating every minute), choose to "Get Info," and set "OpenStickies.app" for its default application. Make sure to check the box that says "Always Open With" to fully automate the process. (Try clicking on “StickiesDatabase.aaa” in Finder to test). Assuming you've made your one-line update with cron, you're now good to go.

Set the utility application "OpenStickies.app" to open files of type "aaa" (top) so that Stickies will come front and center when you click on "StickiesData.aaa" in the Spotlight search window (bottom).
Congratulate Yourself
Let's face it, if you've followed this tutorial, you're up to speed on using Spotlight in your Cocoa apps, you can create custom Spotlight plugins (even for the most contrived situations) and you've enjoyed some good hacking along the way. Bravo.
|
Related Reading Building Cocoa Applications: A Step by Step Guide |
Matthew Russell is a computer scientist from middle Tennessee; and serves Digital Reasoning Systems as the Director of Advanced Technology. Hacking and writing are two activities essential to his renaissance man regimen.
Return to the Mac DevCenter
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 9 of 9.
-
matadata plugins
2007-02-18 02:01:45 PhilipOrr [Reply | View]
-
matadata plugins
2007-02-19 04:55:07 Matthew Russell |
[Reply | View]
I haven't looked into this extensively, but from reviewing Apple's "Spotlight Importer Programming Guide", I'm led to believe that as of now (remember Spotlight is still kinda new), there may not be a great answer. This quote
<blockquote>
New Spotlight importers are detected by comparing the date of the top-level .mdimporter directory.
If the date is the same as a previously loaded importer, the new importer is not detected. If you copy
the updated importer to the Spotlight directory using
cp -r
the change is not noted by Spotlight.
The solution is to either remove the existing importer before copying the updated version, or use the
touch
command on the importer's .mdimporter directory to explicitly update the date
</blockquote>
makes me think that Spotlight is keeping dibs on the directories where plug-ins live, acting accordingly, and there isn't a single file somewhere that gets updated. (Otherwise that doc may have simply had you reference it.) You may want to hit up the Cocoa-dev mailing list and see if anyone knows differently...or if Leopard is going to offer a new way to do this. -
matadata plugins
2007-02-19 15:02:28 PhilipOrr [Reply | View]
Yeah I know It seems a strange way to operate these plugins. I did start an Apple Lists question, though very slow to come up with anything at the moment and Leopards documentation, even with the seeded versions is still very slim to offer up anything.
Phil
-
Package File Formats
2005-07-21 09:00:17 SADev [Reply | View]
Just an FYI - my own importer did not work until I found the Apple "NoteTaker" example code at the URL below. The text file included in the example explains the three vital steps needed to make the importer work with a package:
The relevant text is:
"The import parts of this importer are the changes made to the Info.plist file. First, it use the UTImportedTypeDeclarations instead of UTExportedTypeDeclarations so that if NoteTaker does declare its own UTI for its file format that it will not override the one declared in the importer.
Next, the UTTypeConformsTo section shows how you should declare a file format which is a package. Getting the type hierarchy correct is import for your files to display properly in the Finder and Spotlight search results.
Last, the implementation of GetMetadataForFile() shows how you can get the information out of a package using the Cocoa api's."
Example Link:
http://developer.apple.com/samplecode/Spotlight/listing10.html
-
com.apple.ostype = T78q ?
2005-07-18 11:02:11 SADev [Reply | View]
One other question ... In the article, the com.apple.ostype wasn't highlighted and it was set to, "T78q". Should *all* importers be set to this ostype or is this a mistake in the article? -
com.apple.ostype = T78q ?
2005-07-18 12:39:01 Matthew Russell |
[Reply | View]
That line wasn't highlighted because I didn't think it was all that interesting at the time -- but perhaps it should have been highlighted.
If you take a look at Table 3-2 from Apple's document Understanding UTIs (http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understanding_utis.pdf) , you'll see that ostype is of type OSType. From Wikipedia, you can find a brief summary of OSType here (http://en.wikipedia.org/wiki/OSType) .
To your question "should all importers be set to this ostype" -- No. The 4 character code of type OSType should correspond to the UTI/file extension in question. In our case, we're associating "T78q" with UTI type "aaa". See here (http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understand_utis_conc/chapter_2_section_4.html) for an example with images.) A hint that this association was occuring is because both of these values are wrapped up in a dictionary in the plist.
The "T78q" value I used was the same one from the Apple sample code, and I'm assuming it's not really assigned to anything. Perhaps we could/should have named it "stick" and introduced a "formal" 4 digit OSType value that identified documents of UTI type "aaa".
I hope that helps.
-
Linker errors ...
2005-07-18 06:37:26 SADev [Reply | View]
I'm getting the following during linking ...
/usr/bin/ld: Undefined symbols:
_GetMetadataForFile
.objc_class_name_NSConstantString
.objc_class_name_NSDate
.objc_class_name_NSMutableArray
.objc_class_name_NSMutableAttributedString
.objc_class_name_NSMutableDictionary
.objc_class_name_NSNumber
.objc_class_name_NSObject
.objc_class_name_Protocol
__NSConstantStringClassReference
_objc_msgSend
_objc_msgSendSuper
collect2: ld returned 1 exit status
I've #import'd foundation and cocoa. What's up?
-
Linker errors ...
2005-07-18 07:56:38 Matthew Russell |
[Reply | View]
A couple of things to consider when tackling these kinds of problems:
-Are you using the project file that's provided and getting this error, or did you follow along, building up the project from scratch and get this error? If you followed along, you might want to download the project file provided and compare the two to see what's up. I can build the one provided without any modifications on both XCode 2.0 and 2.1 and get a clean build.
-One thing to pay particular attention to when linking is to remember that while #import-ing things gets you successful compilation, you still have to add the required frameworks to the project (left hand pane under the "External Frameworks..." folder) to get it to link successfully.
-Did you rename GetMetadataForFile.c to GetMetadataForFile.m ? I get an error very similar to the one you get if this file isn't renamed to have a ".m" extension.
Try these things out and let me know what happens. No doubt, your experieces will save someone time when they have similar encounters.







Is it possible to get a list of all mdimporters on the system and what extensions they handle through Cocoa. Something similar to the mdimport -X command.
Thanks
Phil