1This is a guide to the basic machinery an OFX plugin uses to communicate
2with a host application, and goes into the fundamentals of the API.
3
4An example plugin will be used to illustrate how all the machinery
5works, and its source can be found in the C++ file
6``Guide/Code/Example1/basics.cpp``. This plugin is a *no-op* image
7effect and does absolutely nothing to images, it is there purely to show
8you the basics of how a host and plugin work together. I’ll embed
9snippets of the plugin, but with some comments and debug code stripped
10for clarity.
11
12An OFX plugin is a compiled dynamic library that an application can load
13on demand to add extra features to itself. A standardised API is used by
14a host and a plugin to communicate and do what is needed.
15
16OFX has an underlying plugin mechanism that could be used to create a
17wide variety of plugin APIs, but currently only one has been layered on
18top of the base plugin machinery, which is the OFX Image Effect API.
19
20The OFX API is specified using the ``C`` programming language purely by
21a set of header files, there are no libraries a plugin need to link
22against to make a plugin or host work. [1]_
23
24.. __key_concepts_and_terminology:
25
26Key Concepts and Terminology
27============================
28
29OFX has several key concepts and quite specific terminology, which
30definitely need defining.
31
32-  a ``**host**`` is an application than can load OFX plugins and
33   provides an environment for plugins to work in,
34
35-  a ``**plugin**`` provides a set of extra features to a host
36   application,
37
38-  a ``**binary**`` is a dynamic library  [2]_ that contains one or more
39   plugins,
40
41-  a ``**suite**`` is ``C struct`` containing a set of function
42   pointers, which are named and versioned, Suites are the way a host
43   allows a plugin to call functions within it and not have to link
44   against anything,
45
46-  a ``**property**`` is a named object of a restricted set of ``C``
47   types, which is accessed via a property suite,
48
49-  a ``**property set**`` is a collection of properties,
50
51-  an ``**action**`` is a call into a plugin to do something,
52
53-  an ``**API**`` is a collection of suites, actions and properties that
54   are used to do something useful, like process images. APIs are named
55   and versioned.
56
57.. _anchor-bootstrapper_functions:
58
59The Two Bootstrapper Functions
60==============================
61
62To tell the host what it has inside it, a plugin binary needs to expose
63two functions to bootstrap the whole host/plugin communications process.
64These are…
65
66-  ``int OfxGetNumberOfPlugins(void)`` - a function that returns the
67   number of plugins within that binary,
68
69-  ``OfxPlugin *OfxGetPlugin(int nth)`` - a function that returns a
70   ``struct`` that provides the information required by a host to
71   bootstrap the plugin.
72
73The host should load the binary using the appropriate operating system
74calls, then search it for these two exposed symbols. It should then
75iterate over the number of advertised plugins and decide what to do with
76the plugins it finds.
77
78It should go without saying that a host should not hang onto the pointer
79returned by ``OfxGetPlugin`` after it unloads a binary, as the data will
80not be valid. It should also copy any strings out of the struct if it
81wants to keep them.
82
83From our example, we have the following…
84
85**basics.cpp.**
86
87.. code:: c++
88
89    // how many plugins do we have in this binary?
90    int OfxGetNumberOfPlugins(void)
91    {
92      return 1;
93    }
94
95    // return the OfxPlugin struct for the nth plugin
96    OfxPlugin * OfxGetPlugin(int nth)
97    {
98      if(nth == 0)
99        return &effectPluginStruct;
100      return 0;
101    }
102
103.. __the_ofxpluginstruct:
104
105The OfxPluginStruct
106===================
107
108The ``**OfxPluginStruct**`` returned by ``**OfxGetPlugin**`` provides
109information about the implementation of a particular plugin. The
110definition found in the OFX headers is…
111
112**ofxCore.h.**
113
114.. code:: c++
115
116    typedef struct OfxPlugin {
117      const char         *pluginApi;
118      int                 apiVersion;
119      const char         *pluginIdentifier;
120      unsigned int        pluginVersionMajor;
121      unsigned int        pluginVersionMinor;
122      void               (*setHost)(OfxHost *host);
123      OfxPluginEntryPoint *mainEntry;
124    } OfxPlugin;
125
126The fields in the struct give the host enough information to uniquely
127identify the plugin, what it does, and what version it is. These are…
128
129-  ``**pluginAPI**`` - the name of the API that this plugin satisfies,
130   image effect plugins should set this to ``kOfxImageEffectPluginApi``,
131
132-  ``**apiVersion**`` - the version of that API the plug-in was written
133   to,
134
135-  ``**pluginIdentifier**`` - the unique name of the plug-in. Used only
136   to disambiguate the plug-in from all other plug-ins, not necessarily
137   for human eyes,
138
139-  ``**pluginVersionMajor**`` - the major version of the plug-in,
140   typically incremented when compatibility breaks,
141
142-  ``**pluginVersionMinor**`` - the minor version of the plug-in,
143   typically incremented when bugs and so on are fixed,
144
145-  ``**setHost**`` - a function used to set the OfxHost struct in the
146   plugin,
147
148-  ``**mainEntry**`` - the function a host will use to send action
149   requests to the plugin.
150
151Our example plugin’s ``OfxPlugin`` struct looks like…
152
153**basics.cpp.**
154
155.. code:: c++
156
157    static OfxPlugin effectPluginStruct =
158    {
159      kOfxImageEffectPluginApi,
160      1,
161      "org.openeffects:BasicsExamplePlugin",
162      1,
163      0,
164      SetHostFunc,
165      MainEntryPoint
166    };
167
168Using this information a host application can grab a plugin struct then
169figure out if it supports the API at the given version.
170
171The ``**pluginIdentifier**`` is not meant to be the presented to the
172user, it is a purely a unique id for that plugin, *and any related
173versions* of that plugin. Use this for serialisation etc… to identify
174the plugin. The domainname:pluginname nomenclature is suggested best
175practice for a unique id. For a user visible name, use the
176``**kOfxPropVersionLabel**`` property
177
178Plugin versioning allows a plugin (as identified by the
179``**pluginIdentifier**`` field) to be updated and redistributed multiple
180times, with the host knowing which is the most appropriate version to
181use. It even allows old and new versions of the same plugin to be used
182simultaneously within a host application. There are more details on how
183to use the version numbers in the OFX Programming Reference.
184
185The ``**setHost**`` function is used by the host to give the plugin an
186``**OfxHost**`` struct (see below), which is the bit that gives the
187plugin access to functions within the host application.
188
189Finally the ``**mainEntry**`` is the function called by the host to get
190the plugin to carry out actions. Via the property system it behaves as a
191generic function call, allowing arbitrary numbers of parameters to be
192passed to the plugin.
193
194.. __suites:
195
196Suites
197======
198
199A suite is simply a struct with a set of function pointers. Each suite
200is defined by a C struct definition in an OFX header file, as well a C
201literal string that names the suite. A host will pass a set of suites to
202a plugin, each suite having the set of function pointers filled
203appropriately.
204
205For example, look in the file ofxMemory.h for the suite used to perform
206memory allocation…
207
208**ofxMemory.h.**
209
210.. code:: c++
211
212    #define kOfxMemorySuite "OfxMemorySuite"
213
214    typedef struct OfxMemorySuiteV1 {
215      OfxStatus (*memoryAlloc)(void *handle,
216                               size_t nBytes,
217                               void **allocatedData);
218
219      OfxStatus (*memoryFree)(void *allocatedData);
220    } OfxMemorySuiteV1;
221
222Notice also, the version number built into the name of the memory suite.
223If we ever needed to change the memory suite for some reason,
224``OfxMemorySuiteV2`` would be defined, with a new set of function
225pointers. The new suite could then live along side the old suite to
226provide backwards compatibility.
227
228Plugins have to ask for suites from the host by name with a specific
229version, how we do that is covered next.
230
231.. __the_ofxhost_and_fetching_suites:
232
233The OfxHost and Fetching Suites
234-------------------------------
235
236An instance of an ``**OfxHost**`` C struct is the thing that allows a
237plugin to get suites and provides information about a host application,
238it looks like…
239
240**ofxCore.h.**
241
242.. code:: c++
243
244    typedef struct OfxHost {
245      OfxPropertySetHandle host;
246      void *(*fetchSuite)(OfxPropertySetHandle host, const char *suiteName, int suiteVersion);
247    } OfxHost;
248
249A plugin is given one of these by the host application via the
250``**OfxPlugin::setHost**`` function it previously passed to the host.
251
252There are two members to an ``**OfxHost**``, the first is a property set
253(more on properties in a moment) which describes what the host does and
254how it behaves.
255
256The second member is a function used to fetch suites from the host
257application. Going back to our example plugin, we have the following
258bits of code. For the moment ignore how and when the LoadAction is
259called, but notice what it does…
260
261**basics.cpp.**
262
263.. code:: c++
264
265    //  The anonymous namespace is used to hide symbols from export.
266    namespace {
267      OfxHost               *gHost;
268      OfxPropertySuiteV1    *gPropertySuite = 0;
269      OfxImageEffectSuiteV1 *gImageEffectSuite = 0;
270
271      ////////////////////////////////////////////////////////////////////////////////
272      /// call back passed to the host in the OfxPlugin struct to set our host pointer
273      void SetHostFunc(OfxHost *hostStruct)
274      {
275        gHost = hostStruct;
276      }
277
278      ////////////////////////////////////////////////////////////////////////////////
279      /// the first action called
280      OfxStatus LoadAction(void)
281      {
282        gPropertySuite    = (OfxPropertySuiteV1 *) gHost->fetchSuite(gHost->host,
283                                                                     kOfxPropertySuite,
284                                                                     1);
285        gImageEffectSuite = (OfxImageEffectSuiteV1 *) gHost->fetchSuite(gHost->host,
286                                                                        kOfxImageEffectSuite,
287                                                                        1);
288
289        return kOfxStatOK;
290      }
291
292    }
293
294Notice that it is fetching two suites by name from the host. Firstly the
295all important kOfxPropertySuite and then the kOfxImageEffectSuite. It
296squirrels these away for later use in two global pointers. The plugin
297can then use the functions in the suites as and when needed.
298
299.. __properties:
300
301Properties
302==========
303
304The main way plugins and hosts communicate is via the properties
305mechanism. A property is a named object inside a property set, which is
306a bit like a python dictionary. You use the property suite, defined in
307the header ofxProperty.h to access them.
308
309Properties can be of the following fundamental types…
310
311-  ``**int**``
312
313-  ``**double**``
314
315-  ``char *``
316
317-  ``void *``
318
319So for in our example we have….
320
321**basics.cpp.**
322
323.. code:: c++
324
325        OfxPropertySetHandle effectProps;
326        gImageEffectSuite->getPropertySet(effect, &effectProps);
327
328        gPropertySuite->propSetString(effectProps, kOfxPropLabel, 0, "OFX Basics Example");
329
330Here the plugin is using the effect suite to get the property set on the
331effect. It is then setting the string property ``**kOfxPropLabel**`` to
332be "OFX Basics Example". There are corresponding calls for the other
333data types, and equivalent set calls. All pretty straight forwards.
334
335Notice the ``**0**`` passed as the third argument, which is an index.
336Properties can be multidimensional, for example the current pen position
337in a graphics viewport is a 2D integer property. You can get and set
338individual elements in a multidimensional property or you could use
339calls like ``**OfxPropertySuiteV1::propSetIntN**`` to set all values at
340once. Of course there exists *N* calls for all types, as well as
341corresponding setting calls.
342
343The various OFX header files are littered with C macros that define the
344properties used by the API, what type they are, what property set they
345are on and whether you can read and/or write them. The OFX reference
346guide had all the properties listed by name and object they are on, as
347well as what they are for.
348
349By passing information via property sets, rather than fixed C structs,
350you gain a flexibility that allows for simple incremental additions to
351the API without breaking backwards compatibility and builds. It does
352come at a cost (being continual string look-up), but the flexibility it
353gives is worth it.
354
355    **Note**
356
357    Plugins have to be very careful with scope of the pointer returned
358    when you fetch a string property. The pointer will be guaranteed to
359    be valid *only* until the next call to an OFX suite function or
360    until the action ends. If you want to use the string out of those
361    scope you *must* copy it.
362
363.. __actions:
364
365Actions
366=======
367
368Actions are how a host tells a plugin what to do. The ``**mainEntry**``
369function pointer in the ``**OfxPlugin**`` structure is the what accepts
370actions to do whatever is being requested.
371
372The function must conform to the following typedef…
373
374**ofxCore.h.**
375
376.. code:: c++
377
378    typedef  OfxStatus (OfxPluginEntryPoint)(const char *action,
379                                             const void *handle,
380                                             OfxPropertySetHandle inArgs,
381                                             OfxPropertySetHandle outArgs);
382
383Where…
384
385-  ``action`` is a C string that specifies what is to be done by the
386   plugin, e.g. "OfxImageEffectActionRender" tells an image effect
387   plugin to render a frame,
388
389-  ``handle`` is the thing that is being operated on, and needs to be
390   downcast appropriately, what this is will depend on the action,
391
392-  ``inArgs`` is a well defined property set that are the arguments to
393   the action,
394
395-  ``outArgs`` is a well defined property set where a plugin can return
396   values as needed.
397
398The entry point will return an ``OfxStatus`` to tell the host what
399happened. A plugin is not obliged to trap all actions, just a certain
400subset, and if it doesn’t need to trap the action, it can just return
401the status ``**kOfxStatReplyDefault**`` to have the host carry out the
402well defined default for that action.
403
404So looking at our example we can see its main entry point….
405
406**basics.cpp.**
407
408.. code:: c++
409
410      OfxStatus MainEntryPoint(const char *action,
411                               const void *handle,
412                               OfxPropertySetHandle inArgs,
413                               OfxPropertySetHandle outArgs)
414      {
415        // cast to appropriate type
416        OfxImageEffectHandle effect = (OfxImageEffectHandle) handle;
417
418        OfxStatus returnStatus = kOfxStatReplyDefault;
419
420        if(strcmp(action, kOfxActionLoad) == 0) {
421          returnStatus = LoadAction();
422        }
423        else if(strcmp(action, kOfxActionUnload) == 0) {
424          returnStatus = UnloadAction();
425        }
426        else if(strcmp(action, kOfxActionDescribe) == 0) {
427          returnStatus = DescribeAction(effect);
428        }
429        else if(strcmp(action, kOfxImageEffectActionDescribeInContext) == 0) {
430          returnStatus = DescribeInContextAction(effect, inArgs);
431        }
432        else if(strcmp(action, kOfxActionCreateInstance) == 0) {
433          returnStatus = CreateInstanceAction(effect);
434        }
435        else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
436          returnStatus = DestroyInstanceAction(effect);
437        }
438        else if(strcmp(action, kOfxImageEffectActionIsIdentity) == 0) {
439          returnStatus = IsIdentityAction(effect, inArgs, outArgs);
440        }
441
442        return returnStatus;
443      }
444
445You can see the plugin is trapping seven actions and is saying to do the
446default for the rest of the actions.
447
448In fact only four actions need to be trapped for an image effect plugin
449 [3]_, but our machinery plugin is trapping more for illustrative
450purposes.
451
452What is on the property sets, and what the handle is depends on the
453action being called. Some actions have no arguments (eg: the
454kOfxLoadAction), while others have in and out arguments, e.g. the
455kOfxImageEffectActionIsIdentity.
456
457Actions give us a very flexible and expandable generic function calling
458mechanism. This means it is trivial to expand the API via adding extra
459properties or actions to the API without impacting existing plugins or
460applications.
461
462    **Note**
463
464    For the main entry point on image effect plugins, the handle passed
465    in will either be NULL or an ``**OfxImageEffectHandle**``, which is
466    just a blind pointer to host specific data that represents the
467    plugin.
468
469.. __basic_actions_for_image_effect_plugins:
470
471Basic Actions For Image Effect Plugins
472======================================
473
474There are a set of actions called on a plugin that signal to the plugin
475what is going on and to get it to tell the host what the plugin does.
476These need to be called in a specific sequence to make it all work
477properly.
478
479.. __the_load_and_unload_actions:
480
481The Load and Unload Actions
482---------------------------
483
484The kOfxActionLoad is the very first action passed to a plugin. It will
485be called after the ``setHost`` callback has been used to pass the
486OfxHostStruct to the plugin. It is the point at which a plugin gets to
487create global structures that it will later be used across all
488instances. From our `load action snippet <#LoadActionExample>`__ above,
489you can see that the plugin is fetching two suites and caching the
490pointers away for later use.
491
492At some point the host application will want to unload the binary that
493the plugin is contained in, either when the host quits or the plugin is
494no longer needed by the host application. The host needs to notify the
495plugin of this, as it may need to perform some clean up. The
496kOfxActionUnload action is sent to the plugin by the host to warn the
497plugin of it’s imminent demise. After this action is called the host can
498no longer issue any actions to that plugin unless another kOfxActionLoad
499action is called. In our example plugin, the unload does nothing.
500
501    **Note**
502
503    Hosts should always pair the kOfxActionLoad with a kOfxActionUnload,
504    otherwise all sorts of badness can happen, including memory leaks,
505    failing license checks and more. There is one excpetion to this,
506    which is if a plugin encounters an error during the load action and
507    returns an error state. In this case only, the plugin *must* clean
508    up before it returns, and , the balancing unload action is *not*
509    called. In all other circumstances where an error is returned by a
510    plugin from any other action, the unload action will eventually be
511    called.
512
513.. __describing_plugins_to_a_host:
514
515Describing Plugins To A Host
516----------------------------
517
518Once a plugin has had kOfxActionLoad called on it, it will be asked to
519describe itself. This is done with the kOfxActionDescribe action. From
520our example plugin, here is the function called by our main entry point
521in response to the describe action.
522
523**basics.cpp.**
524
525.. code:: c++
526
527      OfxStatus DescribeAction(OfxImageEffectHandle descriptor)
528      {
529        // get the property set handle for the plugin
530        OfxPropertySetHandle effectProps;
531        gImageEffectSuite->getPropertySet(descriptor, &effectProps);
532
533        // set some labels and the group it belongs to
534        gPropertySuite->propSetString(effectProps,
535                                      kOfxPropLabel,
536                                      0,
537                                      "OFX Basics Example");
538        gPropertySuite->propSetString(effectProps,
539                                      kOfxImageEffectPluginPropGrouping,
540                                      0,
541                                      "OFX Example");
542
543        // define the image effects contexts we can be used in, in this case a simple filter
544        gPropertySuite->propSetString(effectProps,
545                                      kOfxImageEffectPropSupportedContexts,
546                                      0,
547                                      kOfxImageEffectContextFilter);
548
549        return kOfxStatOK;
550      }
551
552You will see that it fetches a property set (via the image effect suite)
553and sets various properties on it. Specifically the label used in any
554user interface to name the plugin, and the group of plugins it belongs
555to. The grouping name allows a developer to ask the host to arrange all
556plugins with that group name into a single menu/container in the user
557interface.
558
559The final thing it sets is the single context it can be used in.
560Contexts are specific to image effect plugins, and they are there
561because a plugin can be used in many different ways. We call each way an
562image effect plugin can be used a context. In our example we are saying
563our plugin can behave as a filter only. A filter is simply an effect
564with one and only one input clip and one mandated output clip. This is
565typical of systems such as editors which can drop effects directly onto
566a clip in a time-line. For more complex systems, e.g. a node graph
567compositor, you might want to allow the same plugin to have more input
568clips and a richer parameter set, which we call the general context. A
569plugin can work one or more contexts, not all of which need be supported
570by a host.
571
572Because it can be used in different contexts, and will need to be
573described differently in each, an image effect plugin has a two tier
574description process. First kOfxActionDescribe is called to set
575attributes common to all the contexts the plugin can be used in, then
576the kOfxImageEffectActionDescribeInContext action is called, once for
577each context that the host wants to use the effect in.
578
579Again from our example plugin, here is how it responds to the describe
580in context action…
581
582    **Note**
583
584    A plugin developer might package multiple plugins in a single binary
585    and another multiple plugins into multiple binaries yet both expect
586    them to show up in the same plugin group  [4]_ in the user
587    interface.
588
589**basics.cpp.**
590
591.. code:: c++
592
593      OfxStatus
594      DescribeInContextAction(OfxImageEffectHandle descriptor, OfxPropertySetHandle inArgs)
595      {
596        // check state
597        ERROR_ABORT_IF(gDescribeCalled == false, "DescribeInContextAction called before DescribeAction");
598        gDescribeInContextCalled = true;
599
600        // get the context from the inArgs handle
601        char *context;
602        gPropertySuite->propGetString(inArgs, kOfxImageEffectPropContext, 0, &context);
603
604        ERROR_IF(strcmp(context, kOfxImageEffectContextFilter) != 0, "DescribeInContextAction called on unsupported contex %s", context);
605
606        OfxPropertySetHandle props;
607        // define the mandated single output clip
608        gImageEffectSuite->clipDefine(descriptor, "Output", &props);
609
610        // set the component types we can handle on out output
611        gPropertySuite->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
612        gPropertySuite->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
613
614        // define the mandated single source clip
615        gImageEffectSuite->clipDefine(descriptor, "Source", &props);
616
617        // set the component types we can handle on our main input
618        gPropertySuite->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
619        gPropertySuite->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
620
621        return kOfxStatOK;
622      }
623
624In this case I’ve left the error check cluttering up the snippet so you
625can see how the ``inArgs`` property set is used to specify which context
626is currently being described. Our example then goes on define two image
627clips, the first used for output, and the second used for input. The API
628docs specify that a filter effect needs to specify both of these with
629exactly those names. Not also how the effect is setting a
630multidimensional property associated with each clip to specify what
631pixel types it supports on those clips.
632
633For more complex effects, these actions are the point where you specify
634parameters that the effect wants to use, and get to tweak a whole range
635of settings to say how the plugin behaves.
636
637.. __creating_instances:
638
639Creating Instances
640------------------
641
642So far a host knows what our plugin looks like and how it should behave,
643but it isn’t using it to process pixels yet. At some point a user will
644click on a button in a UI and to say they want to use the plugin. To do
645that a host creates an *instance* of the plugin. An instance represents
646a unique copy of the plugin and contains all the state needed for that.
647For example, a blur plugin may be instantiated many times in a
648compositing graph, each instance will have parameters set to a different
649value, and be connected to different input and output clips.
650
651A plugin developer may need to attach data to each plugin instance,
652typically to tie the plugin into their own image processing
653infrastructure. They get the chance to do that via the
654kOfxActionCreateInstance action. The host will call that action just
655after they have created and initialised their host-side data structures
656that represent the plugin. Our example plugin doesn’t actually do
657anything on create instance, but it could choose to attached it’s own
658data structures to the instance via the ``kOfxPropInstanceData``
659property.
660
661A plugin will also want to destroy any of its own data structures when
662an instance is destroyed. It gets to do that in the
663kOfxActionDestroyInstance action.
664
665Our example plugin exercises both of those action just to illustrate
666what is going it. It simply places a string into the instance data
667property which it later fetches and destroys. In real plugins, this is
668typically a hook to deeper plugin side data structures.
669
670    **Note**
671
672    Because a host might have asynchronous UI handling and multiple
673    render threads on the same instance, it is suggested that a plugin
674    that wants to write to the instance data after instance creation do
675    so in a safe manner (e.g. by semaphore lock).
676
677**basics.cpp.**
678
679.. code:: c++
680
681      OfxStatus CreateInstanceAction(OfxImageEffectHandle instance)
682      {
683        OfxPropertySetHandle effectProps;
684        gImageEffectSuite->getPropertySet(instance, &effectProps);
685
686        // attach some instance data to the effect handle, it can be anything
687        char *myString = strdup("This is random instance data that could be anything you want.");
688
689        // set my private instance data
690        gPropertySuite->propSetPointer(effectProps,
691                                       kOfxPropInstanceData,
692                                       0,
693                                       (void *) myString);
694
695        return kOfxStatOK;
696      }
697
698      // instance destruction
699      OfxStatus DestroyInstanceAction(OfxImageEffectHandle instance)
700      {
701        OfxPropertySetHandle effectProps;
702        gImageEffectSuite->getPropertySet(instance, &effectProps);
703
704        // get my private instance data
705        char *myString = NULL;
706        gPropertySuite->propGetPointer(effectProps,
707                                       kOfxPropInstanceData,
708                                       0,
709                                       (void **) &myString);
710        ERROR_ABORT_IF(myString == NULL, "Instance data should not be null!");
711        free(myString);
712
713        return kOfxStatOK;
714      }
715
716..
717
718    **Note**
719
720    kOfxActionDestroyInstance should always be called when an instance
721    is destroyed, and furthermore all instances need to have had
722    kOfxActionDestroyInstance called on them before kOfxActionUnload can
723    be called.
724
725.. __what_about_the_image_processing:
726
727What About The Image Processing?
728--------------------------------
729
730This plugin is pretty much a *hello world* OFX example, it doesn’t
731actually process any images. Normally a host application would call the
732``**kOfxImageEffectActionRender**`` action when it wants the plugin to
733render a frame. Our simple plugin gets around processing any images by
734trapping the ``**kOfxImageEffectActionIsIdentity**`` action. This action
735lets the plugin tell the host application that it currently does nothing
736to its inputs, for example a blur effect with the blur size of zero. In
737such a case the host can simply ignore the plugin and use its source
738images directly. And here is the code that does that…
739
740**basics.cpp.**
741
742.. code:: c++
743
744      OfxStatus IsIdentityAction( OfxImageEffectHandle instance,
745                                  OfxPropertySetHandle inArgs,
746                                  OfxPropertySetHandle outArgs)
747      {
748        // we set the name of the input clip to pull data from
749        gPropertySuite->propSetString(outArgs, kOfxPropName, 0, "Source");
750        return kOfxStatOK;
751      }
752
753The plugin is telling the host to pass through an unprocessed image from
754an input clip, and because plugins can have more than one input it needs
755to tell the host which clip to use. It does that by setting the
756``kOfxPropName`` property on the outargs. It also returns
757``**kOfxStatOK**`` to indicate that it has trapped the action and that
758the plugin is currently doing nothing.
759
760Remember we said that each action has a well defined set of in and out
761arguments? In the case of the is identity action these are…
762
763-  kOfxPropTime - the time at which to test for identity
764
765-  kOfxImageEffectPropFieldToRender - the field to test for identity
766
767-  kOfxImageEffectPropRenderWindow - the window to test for identity
768   under
769
770-  kOfxImageEffectPropRenderScale - the scale factor being applied to
771   the images being rendered
772
773-  kOfxPropName this to the name of the clip that should be used if the
774   effect is an identity transform, defaults to the empty string
775
776-  kOfxPropTime the time to use from the indicated source clip as an
777   identity image (allowing time slips to happen), defaults to the value
778   in kOfxPropTime in inArgs
779
780A proper plugin would examine the inArgs, its parameters and see if it
781is doing anything to its inputs. If it does need to process images it
782would return ``**kOfxStatReplyDefault**`` rather than
783``**kOfxStatOK**``.
784
785.. __life_cycle_of_a_plugin:
786
787Life Cycle of a Plugin
788======================
789
790Now we’ve outlined the basic actions and functions in a plugin, we
791should clearly specify the calling sequence. Failure to call them in the
792right sequence will lead to all sorts of undefined behaviour.
793
794Assuming the host has done nothing apart from load the dynamic library
795that contains plugins and has found the two `boostrapping
796symbols <#anchor-bootstrapper_functions>`__ in the plugin, the host
797should then…
798
799-  call ``OfxGetNumberOfPlugins`` to discover the number of plugins
800
801-  call ``OfxGetPlugin`` for each of the N plugins in the binary and
802   decide if it can use them or not (by looking at APIs and versions)
803
804At this point the code in the binary should have done nothing apart from
805run those two functions. The host is free to unload the binary at this
806point without further interaction with the plugin.
807
808If the host decides it wants to use one of the plugins in the binary it
809must then…
810
811-  call the ``setHost`` function given to it *for that plugin* and pass
812   back an OfxHost struct which allows plugins to fetch suites
813   appropriate for the API
814
815-  call the ``kOfxActionLoad``
816
817   -  call ``kOfxActionDescribe``
818
819   -  call ``kOfxImageEffectActionDescribeInContext`` for each context
820
821If the host wants to actually use a plugin, it creates whatever host
822side data structures are needed then…
823
824-  calls kOfxActionCreateInstance
825
826When a host wants to get rid of an instance, before it destroys any of
827it’s own data structures it… \*\* calls kOfxActionDestroyInstance
828
829When the host wants to be done with the plugin, and before it
830dynamically unloads the binary it… \* calls ``kOfxActionUnload``, all
831instances *must* have been destroyed before this call.
832
833Once the final kOfxActionUnload has been called, even if it doesn’t
834dynamically unload the binary, the host can no longer call the main
835entry point on that specific plugin until it once more calls
836kOfxActionLoad.
837
838.. __packaging_a_plugin:
839
840Packaging A Plugin
841------------------
842
843The compiled code for a plugin is contained in a dynamic library.
844Plugins are distributed as a directory structure that allows you to add
845icons and other resources you may need. There is more detailed
846information in the OFX Programming Reference Guide.
847
848.. __summary:
849
850Summary
851=======
852
853This example has shown you the basics of the OFX plugin machinery, the
854main things it illustrated was…
855
856-  the `two bootstrapper functions <#anchor-bootstrapper_functions>`__
857   exposed by a plugin that start the plugin discovery process,
858
859-  the main entry point of a plugin is given `actions <#Actions>`__ by
860   the host application to do things,
861
862-  the plugin gets `suites <#Suites>`__ from the host to gain access to
863   functions in the host,
864
865-  `property sets <#Properties>`__ are the main way of passing data back
866   and forth across the API,
867
868-  image effect plugins are
869   `described <#Describing Plugins To A Host>`__ in a two step process,
870
871-  `instances are created <#Creating Instances>`__ when a host wants to
872   use a plugin to do something,
873
874-  actions must be called in a `certain
875   order <#Life Cycle of a Plugin>`__ for the API to work cleanly.
876
877.. [1]
878   Though there exist optional host and plugin support libraries that
879   can be used to help you in your coding.
880
881.. [2]
882   which will be operating system specific
883
884.. [3]
885   kOfxLoadAction, kOfxActionDescribe,
886   kOfxImageEffectActionDescribeInContext and one of
887   kOfxImageEffectActionIsIdentity or kOfxImageEffectActionRender
888
889.. [4]
890   as specified by **kOfxImageEffectPluginPropGrouping**
891