Welcome to the PeekIt PlugIn SDK version 1.0.0
Download SDK


Why Plugins?
PeekIt only supports a few basic data types in it's data formatter section, the ability to build larger structures from those data types seemed to be enough when we first designed the feature. We Were Wrong. People have asked for many other types. And one person even said "why not just make plugins for new data types?" He was a smart guy, so we did what he said.

The universe of data types is huge, and we're never going to support all of them. Covering all the IEEE types alone would be a major effort, much less custom data types you use, and would keep us from adding new features. The answer? Create a plugin model where other smart people could create data formatters that augment what PeekIt has, allowing for a near limitless number of data types that can be presented. The goal is to present data in a human-readable form. Some file data is a particular thing, an IEEE 64 bit float, a number of U.S. dollars, a weight. Presenting this value as the end goal, instead of the raw bytes, can really help someone interprete a file more quickly and effectively.

Our hope is that many formatter plugins will be created. We'll highlight them on Ravenware.com on the new PeekIt Plugins page. See that page for submission guidelines if you want to share a plugin.

Data Formatter Plugin operation overview

Implementation
Download and examine the sample plugin. It's simple enough, but full featured, and should provide most of the information you need to build a plugin.
Formatter plugins are Mac OS X bundles (see ADC's Bundle Programming documentation). The key things that PeekIt extracts from the bundle is the list of plist keys describing the plugin, and entry points for two functions PeekIt will call. All PeekIt formatter plugins have the extension .PIFormPlug. If you don't use that extension then PeekIt will normally not be able to use the plugin.

Note: Plugins are managed by name, the name in the plist. If there are multiple plugins with the same plist name, PeekIt will use the last one loaded. Yes, this could be a problem if people make duplicate named plugins. I'm not going to worry about that (and write the code to manage it) until I get a report of it happening. Yes, that's lazy, but I don't even know if anyone is going to write any plugins, much less conflicting ones, so I'm not going to.

Info.plist Entries
The info.plist provides information PeekIt needs without having to query your plugin programtically. Easier to maintain, easier to read. The info.plist information that PeekIt relies on are the following keys. The keys are defined in PeekitFormatterPlugIn.h.
If a key value is not in the plist file, the default value will be used.

kPIFormandDrawFuncNameKey ("PeekItFormatterFormatAndDrawFunc")
- Name of the function that will format a data string and return a text buffer. PeekIt will use CFBundleGetFunctionPointerForName to extract this entry point from your bundle and call it. Either this or the kPIFormatFuncNameKey must exist or your plugin will be ignored.

kPIFormatFuncNameKey ("PeekItFormatterFormatFunc")
- Name of the function that will format a data string and return a text buffer. PeekIt will use CFBundleGetFunctionPointerForName to extract this entry point from your bundle and call it. Either this or the kPIFormandDrawFuncNameKey must exist or your plugin will be ignored.

kPIPeekItFormatterName ("PeekItFormatterName")
- Name of this formatter required. Should be a single line of text. No default, your plugin will be rejected without a name

kPIAuthorNameKey ("PeekItAuthorName")
- Name of the author of this plugin. Displayed in the Formatter Info pane. Should be a single line of text. Defaults to "unknown".

kPIAuthorOrganizationKey ("PeekItOrganizationName")
- Group, company, team, or other organization that the author of this plugin is affiliated with. Should be a single line of text. Defaults to "unknown".

kPIAuthorEmailKey ("PeekItAuthorEmail")
- Contact email for theis plugin. Should be a single line of text. Defaults to "unknown".

kPIPeekItAuthorWebsiteKey ("PeekItAuthorWebsite")
- Web site for more information or other information the author would like to present. Should be a single line of text. Defaults to "unknown".

kPIFormatterDesc ("PeekItFormatterDesc")
- Description of the operation of this formatter. Can be a short paragraph. Defaults to "unknown".

kPIFormatterBytesConsumed ("PeekItFormatterBytesConsumed")
- How many bytes this formatter needs, or -1 if data defined. Defaults to -1.

kPIFormatterLinesNeeded ("PeekItFormatterLinesNeeded")
- Number of lines needed. Lines is defined as (textSize + 2). Defaults to 1.

The only key that must be present is the kPIPeekItFormatterName key. And, of course, at least one of the two function entry points. PeekIt manages plugins by the text of the kPIPeekItFormatterName key, it must be there or PeekIt will reject the plugin. All the others are optional, though we recommend you use all of them to provide our mutual users with the best experience.

The kPIPeekItFormatterName must also be unique, if PeekIt finds two (or more) plugins with the same kPIPeekItFormatterName key, it will default to using the first one it finds. Use a descriptive name, look at other formatters inside PeekIt (or jsut look at their plist files) to make sure they don't have the name you'd like.

Functions to provide
Each plugin can provide two functions, and must provide at least one. The first takes file data, converts into the appropriate formatting,and draws it into the gaphics context provided. The second takes file data and passes a buffer back that holds a text string of the value.

One of these functions must exist, or the plugin is ignored. If only one function is provided, then of course only that one is used. If both fuctions are provided, PeekIt will use the Draw function. However, future versions of PeekIt will change this, there will be times in the future where both functions will be called on the same file data. Make no assumptions inside your formatting fuctions about who will be called when, or where your results are being presented.
You can return kPIFDisableThisFunction at any point, and the function will no longer be called.
If you have a Format and Draw function and a Format-only fuction, the Draw function is being called. If the Draw function returns kPIFDisableThisFunction PeekIt will stop calling the Draw fuction and switch to the Format-only function for future calls. If the Format-only function subsequently returns kPIFDisableThisFunction then PeekIt will stop calling your plugin completely, until next launch.

If you provide both functions you can also return kPIFRotateFunctions, this will tell PeekIt to stop using the current function and use the other. The term rotate is used instead of alternate for future compatability where there may be more than two functions.

The first function takes a string of hex bytes, converts them to the appropriate text representation internally, then draws the result into the Core Graphics context provided in the rectangle provided. Please only use Core Graphics drawing, QuickDraw is not supported. If we can go to Core Graphics after 20 years of QuickDraw, so can you.

OSStatus SampleNameFormatAndDrawThisByteString(const Ptr inputByteStream,UInt16 numberBytesProvided,UInt32 *bytesConsumed,CGContextRef theCGContext, HIRect rect,UInt32 flags)

Ptr inputByteStream - The stream of bytes to convert.
If you specify a consumed number in kPIFormatterBytesConsumed plist key , then this byte stream will only contain that many bytes or less.
If you specified a variable-length byte stream then this byte stream will contain up to 1024 bytes. It will be LESS than 1024 if there are less than 1024 bytes left in the file. Note that this pointer does not point to actual file data, this is a copy handed to you that will be freed as soon as your function returns.
UInt16 numberBytesProvided - number of bytes provided for conversion.
Also indicates the length of the data stream provided in inputByteStream.
UInt32 *bytesConsumed - Pointer to an unsigned long containing the number of buffer bytes you used to format the data
CGContextRef theCGContext
The graphics context to draw into. Set to PeekIt standard font size and colors. Context has been saved before your function was called, and will be restored to that state after your function returns.
HIRect rec
Rectangle that you can draw into, do not exceed the bounds of that rectangle.
UInt32 flags
Various informational flags, see PeekitFormatterPlugIn.h for the latest information.

The next function takes a string of hex bytes, converts them to the appropriate text representation, and returns that text string to PeekIt for display. Make no assumptions about graphic states or application state when this function is called, PeekIt will call this function at times other than window drawing times.
OSStatus SampleNameFormatThisByteString(const Ptr inputByteStream,UInt16 numberBytesProvided,Ptr *outputTextStream,UInt16 *outputTextStreamLen,UInt32 *bytesConsumed,UInt32 flags)

Ptr inputByteStream - The stream of bytes to convert.
If you specify a consumed number in kPIFormatterBytesConsumed plist key , then this byte stream will only contain that many bytes or less.
If you specified a variable-length byte stream then this byte stream will contain up to 1024 bytes. It will be LESS than 1024 if there are less than 1024 bytes left in the file. Note that this pointer does not point to actual file data, this is a copy handed to you that will be freed as soon as your function returns.
UInt16 numberBytesProvided - number of bytes provided for conversion.
Also indicates the length of the data stream provided in inputByteStream.
Ptr *outputTextStream - A pointer to the location where you should place the text stream result of formatting.
This must be a pointer created by your routine with malloc. PeekIt WILL dispose of this pointer at some point. This must be a string of ASCII/UTF-8 characters, no count word and no termination byte.
UInt16 *outputStreamLen - A pointer to a location where you place the length of the text returned in outputTextStream
UInt32 *bytesConsumed - Pointer to an unsigned long containing the number of buffer bytes you used to format the data
UInt32 flags
Various informational flags, see PeekitFormatterPlugIn.h for the latest information.

PlugIn Return values
noErr (0)
The normal return value.
kPIFDisableThisFunction
Return kPIFDisableThisFunction if you would like PeekIt to stop calling this fuction. If this is the only function your plugin provides, or you've previously disabled the other fuction, returning this value will disable your plugin completely until PeekIt is quit and relaunched.
kPIFExpandDrawingArea, Only accepted as a return value from FPIPluginFormatAndDrawThisByteString
kPIFExpandDrawingArea will add one line height to the rectangle you are able to draw in . PeekIt will assume that you have NOT drawn anything yet, will expand the drawing area and call your function again so you can draw. This of course means that you can continue to return kPIFExpandDrawingArea until you have enough space to draw. The drawing area line height is set to this new height for all subsequent calls to your plugin until PeekIt is launched again, or you resize the height by passing other return values back in the future.
You MUST monitor the flag word passed in to your function! If the flag kPIFUnableToResizeDrawingArea is passed in, that means that PeekIt is unable to expand or compress the drawing any further and you MUST do your best to draw something, you will not be called again for this particular file position no matter what you return. This is NOT static, the next time your function is called the drawing area may again be resizable, just be certain to check the flag.
kPIFCompressDrawingArea, Only accepted as a return value from FPIPluginFormatAndDrawThisByteString
kPIFCompressDrawingArea will subtract one line height to the rectangle you are able to draw in PeekIt will assume that you have NOT drawn anything yet, will compress the drawing area and call your function again so you can draw.
This of course means that you can continue to return kPIFCompressDrawingArea until you have enough space to draw.
You MUST monitor the flag word passed in to your function!
If the flag kPIFUnableToResizeDrawingArea is passed in, that means that PeekIt is unable to expand or compress the drawing any further and you MUST do your best to draw something, you will not be called again for this particular file position no matter what you return. This is NOT static, the next time your function is called the drawing area may again be resizable, just be certain to check the flag.
kPIFRotateFunctions
kPIFRotateFunction can be returned from either function and tells PeekIt to stop using this function and switch to the other function. Ignored if your plugin only maintains one function. Similar to the drawing resize return codes, PeekIt will assume that you have not done any drawing or formatting, and will immediately call your alternate function with the current file data. The term rotate is used instead of alternate for future compatability where there may be more than two functions. You can only rotate functions once for a data value to prevent inadvertent infinite looping. If this is a problem, send us an email and explain why it would be useful to switch multiple times. Keep in mind that switching once, with the subsequent re-call, allows both functions to be called for every value.

 

Code Implementation
PeekIt is a straight C, Carbon application built with gcc version 4.0 or later. I have not, and will not, test other versions of gcc, thought they probably will work.Your functions are entered as straight C. What you do inside your plugin is up to you, just don't expect anything to be readied except Carbon frameworks, and don't assume there is any C++ exception handling or Objective-C runtime, or other non-straight C facilities present. And longjmps are right out.....

Other Details

If you have a plugin you think people might be interested in, put it in a .zip archive and email it to pifplugins at ravenware.com . I will post it to the Ravenware site. We reserve the right to refuse posting of any plugin, and the right to remove any plugin from the site, with no notice and no reason given.
Providing source code of course will make it more interesting to people.

There is no support, debugging, or additional guidance available for building PeekIt formatter plugins. Please report bugs, that's the best support mechanism, and check this page occasionally for updates.

Documentation written by Alex Kinnison.

Copyright 2006 Ravenware Industries, LLC