1 /*
2 Software License :
3
4 Copyright (c) 2014, The Open Effects Association Ltd. All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14 * Neither the name The Open Effects Association Ltd, nor the names of its
15 contributors may be used to endorse or promote products derived from this
16 software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 Author : Bruno Nicoletti (2014)
32
33 This plugin will take you through the basics of defining and using
34 parameters as well as how to use instance data.
35
36 The accompanying guide will explain what is happening in more detail.
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <math.h>
43
44 #include <string>
45 #include <iostream>
46
47 // the one OFX header we need, it includes the others necessary
48 #include "ofxImageEffect.h"
49
50 #if defined __APPLE__ || defined linux || defined __DragonFly__
51 # define EXPORT __attribute__((visibility("default")))
52 #elif defined _WIN32
53 # define EXPORT OfxExport
54 #else
55 # error Not building on your operating system quite yet
56 #endif
57
58 ////////////////////////////////////////////////////////////////////////////////
59 // macro to write a labelled message to stderr with
60 #ifdef _WIN32
61 #define DUMP(LABEL, MSG, ...) \
62 { \
63 fprintf(stderr, "%s%s:%d in %s ", LABEL, __FILE__, __LINE__, __FUNCTION__); \
64 fprintf(stderr, MSG, ##__VA_ARGS__); \
65 fprintf(stderr, "\n"); \
66 }
67 #else
68 #define DUMP(LABEL, MSG, ...) \
69 { \
70 fprintf(stderr, "%s%s:%d in %s ", LABEL, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
71 fprintf(stderr, MSG, ##__VA_ARGS__); \
72 fprintf(stderr, "\n"); \
73 }
74 #endif
75
76 // macro to write a simple message, only works if 'VERBOSE' is #defined
77 //#define VERBOSE
78 #ifdef VERBOSE
79 # define MESSAGE(MSG, ...) DUMP("", MSG, ##__VA_ARGS__)
80 #else
81 # define MESSAGE(MSG, ...)
82 #endif
83
84 // macro to dump errors to stderr if the given condition is true
85 #define ERROR_IF(CONDITION, MSG, ...) if(CONDITION) { DUMP("ERROR : ", MSG, ##__VA_ARGS__);}
86
87 // macro to dump errors to stderr and abort if the given condition is true
88 #define ERROR_ABORT_IF(CONDITION, MSG, ...) \
89 { \
90 if(CONDITION) { \
91 DUMP("FATAL ERROR : ", MSG, ##__VA_ARGS__); \
92 abort(); \
93 } \
94 }
95
96 // name of our two params
97 #define GAIN_PARAM_NAME "gain"
98 #define APPLY_TO_ALPHA_PARAM_NAME "applyToAlpha"
99
100 // anonymous namespace to hide our symbols in
101 namespace {
102 ////////////////////////////////////////////////////////////////////////////////
103 // set of suite pointers provided by the host
104 OfxHost *gHost;
105 OfxPropertySuiteV1 *gPropertySuite = 0;
106 OfxImageEffectSuiteV1 *gImageEffectSuite = 0;
107 OfxParameterSuiteV1 *gParameterSuite = 0;
108
109 ////////////////////////////////////////////////////////////////////////////////
110 // our instance data, where we are caching away clip and param handles
111 struct MyInstanceData {
112 // handles to the clips we deal with
113 OfxImageClipHandle sourceClip;
114 OfxImageClipHandle outputClip;
115
116 // handles to a our parameters
117 OfxParamHandle gainParam;
118 OfxParamHandle applyToAlphaParam;
119 };
120
121 ////////////////////////////////////////////////////////////////////////////////
122 // get my instance data from a property set handle
FetchInstanceData(OfxPropertySetHandle effectProps)123 MyInstanceData *FetchInstanceData(OfxPropertySetHandle effectProps)
124 {
125 MyInstanceData *myData = 0;
126 gPropertySuite->propGetPointer(effectProps,
127 kOfxPropInstanceData,
128 0,
129 (void **) &myData);
130 return myData;
131 }
132
133 ////////////////////////////////////////////////////////////////////////////////
134 // get my instance data
FetchInstanceData(OfxImageEffectHandle effect)135 MyInstanceData *FetchInstanceData(OfxImageEffectHandle effect)
136 {
137 // get the property handle for the plugin
138 OfxPropertySetHandle effectProps;
139 gImageEffectSuite->getPropertySet(effect, &effectProps);
140
141 // and get the instance data out of that
142 return FetchInstanceData(effectProps);
143 }
144
145 ////////////////////////////////////////////////////////////////////////////////
146 // get the named suite and put it in the given pointer, with error checking
147 template <class SUITE>
FetchSuite(SUITE * & suite,const char * suiteName,int suiteVersion)148 void FetchSuite(SUITE *& suite, const char *suiteName, int suiteVersion)
149 {
150 suite = (SUITE *) gHost->fetchSuite(gHost->host, suiteName, suiteVersion);
151 if(!suite) {
152 ERROR_ABORT_IF(suite == NULL,
153 "Failed to fetch %s verison %d from the host.",
154 suiteName,
155 suiteVersion);
156 }
157 }
158
159 ////////////////////////////////////////////////////////////////////////////////
160 // The first _action_ called after the binary is loaded (three boot strapper functions will be howeever)
LoadAction(void)161 OfxStatus LoadAction(void)
162 {
163 // fetch our three suites
164 FetchSuite(gPropertySuite, kOfxPropertySuite, 1);
165 FetchSuite(gImageEffectSuite, kOfxImageEffectSuite, 1);
166 FetchSuite(gParameterSuite, kOfxParameterSuite, 1);
167
168 return kOfxStatOK;
169 }
170
171 ////////////////////////////////////////////////////////////////////////////////
172 // the plugin's basic description routine
DescribeAction(OfxImageEffectHandle descriptor)173 OfxStatus DescribeAction(OfxImageEffectHandle descriptor)
174 {
175 // get the property set handle for the plugin
176 OfxPropertySetHandle effectProps;
177 gImageEffectSuite->getPropertySet(descriptor, &effectProps);
178
179 // set some labels and the group it belongs to
180 gPropertySuite->propSetString(effectProps,
181 kOfxPropLabel,
182 0,
183 "OFX Gain Example");
184 gPropertySuite->propSetString(effectProps,
185 kOfxImageEffectPluginPropGrouping,
186 0,
187 "OFX Example");
188
189 // define the image effects contexts we can be used in, in this case a simple filter
190 gPropertySuite->propSetString(effectProps,
191 kOfxImageEffectPropSupportedContexts,
192 0,
193 kOfxImageEffectContextFilter);
194
195 // set the bit depths the plugin can handle
196 gPropertySuite->propSetString(effectProps,
197 kOfxImageEffectPropSupportedPixelDepths,
198 0,
199 kOfxBitDepthFloat);
200 gPropertySuite->propSetString(effectProps,
201 kOfxImageEffectPropSupportedPixelDepths,
202 1,
203 kOfxBitDepthShort);
204 gPropertySuite->propSetString(effectProps,
205 kOfxImageEffectPropSupportedPixelDepths,
206 2,
207 kOfxBitDepthByte);
208
209 // say that a single instance of this plugin can be rendered in multiple threads
210 gPropertySuite->propSetString(effectProps,
211 kOfxImageEffectPluginRenderThreadSafety,
212 0,
213 kOfxImageEffectRenderFullySafe);
214
215 // say that the host should manage SMP threading over a single frame
216 gPropertySuite->propSetInt(effectProps,
217 kOfxImageEffectPluginPropHostFrameThreading,
218 0,
219 1);
220
221
222 return kOfxStatOK;
223 }
224
225 ////////////////////////////////////////////////////////////////////////////////
226 // describe the plugin in context
227 OfxStatus
DescribeInContextAction(OfxImageEffectHandle descriptor,OfxPropertySetHandle)228 DescribeInContextAction(OfxImageEffectHandle descriptor,
229 OfxPropertySetHandle /*inArgs*/)
230 {
231 OfxPropertySetHandle props;
232 // define the mandated single output clip
233 gImageEffectSuite->clipDefine(descriptor, "Output", &props);
234
235 // set the component types we can handle on out output
236 gPropertySuite->propSetString(props,
237 kOfxImageEffectPropSupportedComponents,
238 0,
239 kOfxImageComponentRGBA);
240 gPropertySuite->propSetString(props,
241 kOfxImageEffectPropSupportedComponents,
242 1,
243 kOfxImageComponentAlpha);
244 gPropertySuite->propSetString(props,
245 kOfxImageEffectPropSupportedComponents,
246 2,
247 kOfxImageComponentRGB);
248
249 // define the mandated single source clip
250 gImageEffectSuite->clipDefine(descriptor, "Source", &props);
251
252 // set the component types we can handle on our main input
253 gPropertySuite->propSetString(props,
254 kOfxImageEffectPropSupportedComponents,
255 0,
256 kOfxImageComponentRGBA);
257 gPropertySuite->propSetString(props,
258 kOfxImageEffectPropSupportedComponents,
259 1,
260 kOfxImageComponentAlpha);
261 gPropertySuite->propSetString(props,
262 kOfxImageEffectPropSupportedComponents,
263 2,
264 kOfxImageComponentRGB);
265
266 // first get the handle to the parameter set
267 OfxParamSetHandle paramSet;
268 gImageEffectSuite->getParamSet(descriptor, ¶mSet);
269
270 // properties on our parameter
271 OfxPropertySetHandle paramProps;
272
273 // now define a 'gain' parameter and set its properties
274 gParameterSuite->paramDefine(paramSet,
275 kOfxParamTypeDouble,
276 GAIN_PARAM_NAME,
277 ¶mProps);
278 gPropertySuite->propSetString(paramProps,
279 kOfxParamPropDoubleType,
280 0,
281 kOfxParamDoubleTypeScale);
282 gPropertySuite->propSetDouble(paramProps,
283 kOfxParamPropDefault,
284 0,
285 1.0);
286 gPropertySuite->propSetDouble(paramProps,
287 kOfxParamPropMin,
288 0,
289 0.0);
290 gPropertySuite->propSetDouble(paramProps,
291 kOfxParamPropDisplayMin,
292 0,
293 0.0);
294 gPropertySuite->propSetDouble(paramProps,
295 kOfxParamPropDisplayMax,
296 0,
297 10.0);
298 gPropertySuite->propSetString(paramProps,
299 kOfxPropLabel,
300 0,
301 "Gain");
302 gPropertySuite->propSetString(paramProps,
303 kOfxParamPropHint,
304 0,
305 "How much to multiply the image by.");
306
307 // and define the 'applyToAlpha' parameters and set its properties
308 gParameterSuite->paramDefine(paramSet,
309 kOfxParamTypeBoolean,
310 APPLY_TO_ALPHA_PARAM_NAME,
311 ¶mProps);
312 gPropertySuite->propSetInt(paramProps,
313 kOfxParamPropDefault,
314 0,
315 0);
316 gPropertySuite->propSetString(paramProps,
317 kOfxParamPropHint,
318 0,
319 "Whether to apply the gain value to alpha as well.");
320 gPropertySuite->propSetString(paramProps,
321 kOfxPropLabel,
322 0,
323 "Apply To Alpha");
324
325 return kOfxStatOK;
326 }
327
328 ////////////////////////////////////////////////////////////////////////////////
329 /// instance construction
CreateInstanceAction(OfxImageEffectHandle instance)330 OfxStatus CreateInstanceAction( OfxImageEffectHandle instance)
331 {
332 OfxPropertySetHandle effectProps;
333 gImageEffectSuite->getPropertySet(instance, &effectProps);
334
335 // To avoid continual lookup, put our handles into our instance
336 // data, those handles are guaranteed to be valid for the duration
337 // of the instance.
338 MyInstanceData *myData = new MyInstanceData;
339
340 // Set my private instance data
341 gPropertySuite->propSetPointer(effectProps, kOfxPropInstanceData, 0, (void *) myData);
342
343 // Cache the source and output clip handles
344 gImageEffectSuite->clipGetHandle(instance, "Source", &myData->sourceClip, 0);
345 gImageEffectSuite->clipGetHandle(instance, "Output", &myData->outputClip, 0);
346
347 // Cache away the param handles
348 OfxParamSetHandle paramSet;
349 gImageEffectSuite->getParamSet(instance, ¶mSet);
350 gParameterSuite->paramGetHandle(paramSet,
351 GAIN_PARAM_NAME,
352 &myData->gainParam,
353 0);
354 gParameterSuite->paramGetHandle(paramSet,
355 APPLY_TO_ALPHA_PARAM_NAME,
356 &myData->applyToAlphaParam,
357 0);
358
359 return kOfxStatOK;
360 }
361
362 ////////////////////////////////////////////////////////////////////////////////
363 // instance destruction
DestroyInstanceAction(OfxImageEffectHandle instance)364 OfxStatus DestroyInstanceAction( OfxImageEffectHandle instance)
365 {
366 // get my instance data
367 MyInstanceData *myData = FetchInstanceData(instance);
368 delete myData;
369
370 return kOfxStatOK;
371 }
372
373 ////////////////////////////////////////////////////////////////////////////////
374 // Look up a pixel in the image. returns null if the pixel was not
375 // in the bounds of the image
376 template <class T>
pixelAddress(int x,int y,void * baseAddress,OfxRectI bounds,int rowBytes,int nCompsPerPixel)377 static inline T * pixelAddress(int x, int y,
378 void *baseAddress,
379 OfxRectI bounds,
380 int rowBytes,
381 int nCompsPerPixel)
382 {
383 // Inside the bounds of this image?
384 if(x < bounds.x1 || x >= bounds.x2 || y < bounds.y1 || y >= bounds.y2)
385 return NULL;
386
387 // turn image plane coordinates into offsets from the bottom left
388 int yOffset = y - bounds.y1;
389 int xOffset = x - bounds.x1;
390
391 // Find the start of our row, using byte arithmetic
392 void *rowStartAsVoid = reinterpret_cast<char *>(baseAddress) + yOffset * rowBytes;
393
394 // turn the row start into a pointer to our data type
395 T *rowStart = reinterpret_cast<T *>(rowStartAsVoid);
396
397 // finally find the position of the first component of column
398 return rowStart + (xOffset * nCompsPerPixel);
399 }
400
401 ////////////////////////////////////////////////////////////////////////////////
402 // iterate over our pixels and process them
403 template <class T, int MAX>
PixelProcessing(double gain,bool applyToAlpha,OfxImageEffectHandle instance,OfxPropertySetHandle sourceImg,OfxPropertySetHandle outputImg,OfxRectI renderWindow,int nComps)404 void PixelProcessing(double gain,
405 bool applyToAlpha,
406 OfxImageEffectHandle instance,
407 OfxPropertySetHandle sourceImg,
408 OfxPropertySetHandle outputImg,
409 OfxRectI renderWindow,
410 int nComps)
411 {
412 // fetch output image info from the property handle
413 int dstRowBytes;
414 OfxRectI dstBounds;
415 void *dstPtr = NULL;
416 gPropertySuite->propGetInt(outputImg, kOfxImagePropRowBytes, 0, &dstRowBytes);
417 gPropertySuite->propGetIntN(outputImg, kOfxImagePropBounds, 4, &dstBounds.x1);
418 gPropertySuite->propGetPointer(outputImg, kOfxImagePropData, 0, &dstPtr);
419
420 if(dstPtr == NULL) {
421 throw "Bad destination pointer";
422 }
423
424 // fetch input image info from the property handle
425 int srcRowBytes;
426 OfxRectI srcBounds;
427 void *srcPtr = NULL;
428 gPropertySuite->propGetInt(sourceImg, kOfxImagePropRowBytes, 0, &srcRowBytes);
429 gPropertySuite->propGetIntN(sourceImg, kOfxImagePropBounds, 4, &srcBounds.x1);
430 gPropertySuite->propGetPointer(sourceImg, kOfxImagePropData, 0, &srcPtr);
431
432 if(srcPtr == NULL) {
433 throw "Bad source pointer";
434 }
435
436 // and do some processing
437 for(int y = renderWindow.y1; y < renderWindow.y2; y++) {
438 if(y % 20 == 0 && gImageEffectSuite->abort(instance)) break;
439
440 // get the row start for the output image
441 T *dstPix = pixelAddress<T>(renderWindow.x1, y,
442 dstPtr,
443 dstBounds,
444 dstRowBytes,
445 nComps);
446
447 for(int x = renderWindow.x1; x < renderWindow.x2; x++) {
448
449 // get the source pixel
450 T *srcPix = pixelAddress<T>(x, y,
451 srcPtr,
452 srcBounds,
453 srcRowBytes,
454 nComps);
455
456 if(srcPix) {
457 // we have one, iterate each component in the pixels
458 for(int i = 0; i < nComps; ++i) {
459 if(i != 3 || applyToAlpha) {
460 // multiply our source component by our gain value
461 double value = *srcPix * gain;
462
463 // if it has gone out of legal bounds, clamp it
464 if(MAX != 1) { // we let floating point pixels over and underflow
465 value = value < 0 ? 0 : (value > MAX ? MAX : value);
466 }
467 *dstPix = T(value);
468 }
469 else {
470 *dstPix = *srcPix;
471 }
472 // increment to next component
473 ++dstPix; ++srcPix;
474 }
475 }
476 else {
477 // we don't have a pixel in the source image, set output to zero
478 for(int i = 0; i < nComps; ++i) {
479 *dstPix = 0;
480 ++dstPix;
481 }
482 }
483 }
484 }
485 }
486
487
488 ////////////////////////////////////////////////////////////////////////////////
489 // Render an output image
RenderAction(OfxImageEffectHandle instance,OfxPropertySetHandle inArgs,OfxPropertySetHandle)490 OfxStatus RenderAction( OfxImageEffectHandle instance,
491 OfxPropertySetHandle inArgs,
492 OfxPropertySetHandle /*outArgs*/)
493 {
494 // get the render window and the time from the inArgs
495 OfxTime time;
496 OfxRectI renderWindow;
497 OfxStatus status = kOfxStatOK;
498
499 gPropertySuite->propGetDouble(inArgs, kOfxPropTime, 0, &time);
500 gPropertySuite->propGetIntN(inArgs, kOfxImageEffectPropRenderWindow, 4, &renderWindow.x1);
501
502 // get our instance data which has out clip and param handles
503 MyInstanceData *myData = FetchInstanceData(instance);
504
505 // get our param values
506 double gain = 1.0;
507 int applyToAlpha = 0;
508 gParameterSuite->paramGetValueAtTime(myData->gainParam, time, &gain);
509 gParameterSuite->paramGetValueAtTime(myData->applyToAlphaParam, time, &applyToAlpha);
510
511
512 // the property sets holding our images
513 OfxPropertySetHandle outputImg = NULL, sourceImg = NULL;
514 try {
515 // fetch image to render into from that clip
516 OfxPropertySetHandle outputImg;
517 if(gImageEffectSuite->clipGetImage(myData->outputClip, time, NULL, &outputImg) != kOfxStatOK) {
518 throw " no output image!";
519 }
520
521 // fetch image at render time from that clip
522 if (gImageEffectSuite->clipGetImage(myData->sourceClip, time, NULL, &sourceImg) != kOfxStatOK) {
523 throw " no source image!";
524 }
525
526 // figure out the data types
527 const char *cstr;
528 gPropertySuite->propGetString(outputImg, kOfxImageEffectPropComponents, 0, &cstr);
529 std::string components = cstr;
530
531 // how many components per pixel?
532 int nComps = 0;
533 if(components == kOfxImageComponentRGBA) {
534 nComps = 4;
535 }
536 else if(components == kOfxImageComponentRGB) {
537 nComps = 3;
538 }
539 else if(components == kOfxImageComponentAlpha) {
540 nComps = 1;
541 }
542 else {
543 throw " bad pixel type!";
544 }
545
546 // now do our render depending on the data type
547 gPropertySuite->propGetString(outputImg, kOfxImageEffectPropPixelDepth, 0, &cstr);
548 std::string dataType = cstr;
549
550 if(dataType == kOfxBitDepthByte) {
551 PixelProcessing<unsigned char, 255>(gain, applyToAlpha != 0,
552 instance, sourceImg, outputImg, renderWindow, nComps);
553 }
554 else if(dataType == kOfxBitDepthShort) {
555 PixelProcessing<unsigned short, 65535>(gain, applyToAlpha != 0,
556 instance, sourceImg, outputImg, renderWindow, nComps);
557 }
558 else if (dataType == kOfxBitDepthFloat) {
559 PixelProcessing<float, 1>(gain, applyToAlpha != 0,
560 instance, sourceImg, outputImg, renderWindow, nComps);
561 }
562 else {
563 throw " bad data type!";
564 }
565
566 }
567 catch(const char *errStr ) {
568 bool isAborting = gImageEffectSuite->abort(instance);
569
570 // if we were interrupted, the failed fetch is fine, just return kOfxStatOK
571 // otherwise, something wierd happened
572 if(!isAborting) {
573 status = kOfxStatFailed;
574 }
575 ERROR_IF(!isAborting, " Rendering failed because %s", errStr);
576
577 }
578
579 if(sourceImg)
580 gImageEffectSuite->clipReleaseImage(sourceImg);
581 if(outputImg)
582 gImageEffectSuite->clipReleaseImage(outputImg);
583
584 // all was well
585 return status;
586 }
587
588 // are the settings of the effect making it redundant and so not do anything to the image data
IsIdentityAction(OfxImageEffectHandle instance,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)589 OfxStatus IsIdentityAction( OfxImageEffectHandle instance,
590 OfxPropertySetHandle inArgs,
591 OfxPropertySetHandle outArgs)
592 {
593 MyInstanceData *myData = FetchInstanceData(instance);
594
595 double time;
596 gPropertySuite->propGetDouble(inArgs, kOfxPropTime, 0, &time);
597
598 double gain = 1.0;
599 gParameterSuite->paramGetValueAtTime(myData->gainParam, time, &gain);
600
601 // if the gain value is 1.0 (or nearly so) say we aren't doing anything
602 if(fabs(gain - 1.0) < 0.000000001) {
603 // we set the name of the input clip to pull default images from
604 gPropertySuite->propSetString(outArgs, kOfxPropName, 0, "Source");
605 // and say we trapped the action and we are at the identity
606 return kOfxStatOK;
607 }
608
609 // say we aren't at the identity
610 return kOfxStatReplyDefault;
611 }
612
613 ////////////////////////////////////////////////////////////////////////////////
614 // Call back passed to the host in the OfxPlugin struct to set our host pointer
615 //
616 // This must be called AFTER both OfxGetNumberOfPlugins and OfxGetPlugin, but
617 // before the pluginMain entry point is ever touched.
SetHostFunc(OfxHost * hostStruct)618 void SetHostFunc(OfxHost *hostStruct)
619 {
620 gHost = hostStruct;
621 }
622
623 ////////////////////////////////////////////////////////////////////////////////
624 // The main entry point function, the host calls this to get the plugin to do things.
MainEntryPoint(const char * action,const void * handle,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)625 OfxStatus MainEntryPoint(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
626 {
627 MESSAGE(": START action is : %s \n", action );
628 // cast to appropriate type
629 OfxImageEffectHandle effect = (OfxImageEffectHandle) handle;
630
631 OfxStatus returnStatus = kOfxStatReplyDefault;
632
633 if(strcmp(action, kOfxActionLoad) == 0) {
634 // The very first action called on a plugin.
635 returnStatus = LoadAction();
636 }
637 else if(strcmp(action, kOfxActionDescribe) == 0) {
638 // the first action called to describe what the plugin does
639 returnStatus = DescribeAction(effect);
640 }
641 else if(strcmp(action, kOfxImageEffectActionDescribeInContext) == 0) {
642 // the second action called to describe what the plugin does in a specific context
643 returnStatus = DescribeInContextAction(effect, inArgs);
644 }
645 else if(strcmp(action, kOfxActionCreateInstance) == 0) {
646 // the action called when an instance of a plugin is created
647 returnStatus = CreateInstanceAction(effect);
648 }
649 else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
650 // the action called when an instance of a plugin is destroyed
651 returnStatus = DestroyInstanceAction(effect);
652 }
653 else if(strcmp(action, kOfxImageEffectActionIsIdentity) == 0) {
654 // Check to see if our param settings cause nothing to happen
655 returnStatus = IsIdentityAction(effect, inArgs, outArgs);
656 }
657 else if(strcmp(action, kOfxImageEffectActionRender) == 0) {
658 // action called to render a frame
659 returnStatus = RenderAction(effect, inArgs, outArgs);
660 }
661
662 MESSAGE(": END action is : %s \n", action );
663 /// other actions to take the default value
664 return returnStatus;
665 }
666
667 } // end of anonymous namespace
668
669
670 ////////////////////////////////////////////////////////////////////////////////
671 // The plugin struct passed back to the host application to initiate bootstrapping\
672 // of plugin communications
673 static OfxPlugin effectPluginStruct =
674 {
675 kOfxImageEffectPluginApi, // The API this plugin satisfies.
676 1, // The version of the API it satisifes.
677 "org.openeffects:GainExamplePlugin", // The unique ID of this plugin.
678 1, // The major version number of this plugin.
679 0, // The minor version number of this plugin.
680 SetHostFunc, // Function used to pass back to the plugin the OFXHost struct.
681 MainEntryPoint // The main entry point to the plugin where all actions are passed to.
682 };
683
684 ////////////////////////////////////////////////////////////////////////////////
685 // The first of the two functions that a host application will look for
686 // after loading the binary, this function returns the number of plugins within
687 // this binary.
688 //
689 // This will be the first function called by the host.
OfxGetNumberOfPlugins(void)690 EXPORT int OfxGetNumberOfPlugins(void)
691 {
692 return 1;
693 }
694
695 ////////////////////////////////////////////////////////////////////////////////
696 // The second of the two functions that a host application will look for
697 // after loading the binary, this function returns the 'nth' plugin declared in
698 // this binary.
699 //
700 // This will be called multiple times by the host, once for each plugin present.
OfxGetPlugin(int nth)701 EXPORT OfxPlugin * OfxGetPlugin(int nth)
702 {
703 if(nth == 0)
704 return &effectPluginStruct;
705 return 0;
706 }
707