1 /*
2 Software License :
3
4 Copyright (c) 2003, 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 Ofx Example plugin that shows how a custom parameters are managed.
32
33 It is meant to illustrate certain features of the API, as opposed to being a perfectly
34 crafted piece of image processing software.
35 */
36
37 #ifdef WIN32
38 #include <windows.h>
39 #endif
40
41 #include <cstring>
42 #include <cstdio>
43 #ifdef __APPLE__
44 #include <OpenGL/gl.h>
45 #else
46 #include <GL/gl.h>
47 #endif
48 #include <cmath>
49 #include <stdexcept>
50 #include <new>
51 #include "ofxImageEffect.h"
52 #include "ofxMemory.h"
53 #include "ofxMultiThread.h"
54
55 #include "../include/ofxUtilities.H" // example support utils
56
57 #if defined __APPLE__ || defined linux || defined __DragonFly__
58 # define EXPORT __attribute__((visibility("default")))
59 #elif defined _WIN32
60 # define EXPORT OfxExport
61 #else
62 # error Not building on your operating system quite yet
63 #endif
64
65 #define kPointParam "point"
66
67 // pointers to various bits of the host
68 OfxHost *gHost;
69 OfxImageEffectSuiteV1 *gEffectHost = 0;
70 OfxPropertySuiteV1 *gPropHost = 0;
71 OfxParameterSuiteV1 *gParamHost = 0;
72 OfxMemorySuiteV1 *gMemoryHost = 0;
73 OfxMultiThreadSuiteV1 *gThreadHost = 0;
74 OfxMessageSuiteV1 *gMessageSuite = 0;
75 OfxInteractSuiteV1 *gInteractHost = 0;
76
77 // decode a custom param from a string
78 static OfxStatus
parseCustomParam(const char * str,double & x,double & y)79 parseCustomParam(const char *str, double &x, double &y)
80 {
81 if(str && *str) {
82 int nRead = sscanf(str, "%lg %lg", &x, &y);
83 if(nRead != 2)
84 return kOfxStatErrFormat; // HACK need better error codes
85 }
86 else
87 return kOfxStatErrFormat; // HACK need better error codes
88 return kOfxStatOK;
89 }
90
91 // encode a custom param into a string
92 void
writeCustomParam(char * str,int strlen,double x,double y)93 writeCustomParam(char *str, int strlen, double x, double y)
94 {
95 #ifdef WIN32
96 _snprintf(str, strlen, "%lg %lg", x, y);
97 #else
98 snprintf(str, strlen, "%lg %lg", x, y);
99 #endif
100 }
101
102 // set the current value of my custom parameter
103 static OfxStatus
getCustomParam(OfxImageEffectHandle pluginInstance,double & x,double & y)104 getCustomParam(OfxImageEffectHandle pluginInstance, double &x, double &y)
105 {
106 // get the parameter set from the effect
107 OfxParamSetHandle paramSet;
108 gEffectHost->getParamSet(pluginInstance, ¶mSet);
109
110 // get the parameter from the parameter set
111 OfxParamHandle param;
112 gParamHost->paramGetHandle(paramSet, kPointParam, ¶m, NULL);
113
114 // get my custom param's raw value
115 char *str = 0;
116 gParamHost->paramGetValue(param, &str);
117
118 return parseCustomParam(str, x, y);
119 }
120
121 // get the current value of my custom parameter
122 static OfxStatus
setCustomParam(OfxImageEffectHandle pluginInstance,double x,double y)123 setCustomParam(OfxImageEffectHandle pluginInstance, double x, double y)
124 {
125 // encode the custom parameter
126 char str[1024];
127 writeCustomParam(str, 1024, x, y);
128
129 // get the parameter set from the effect
130 OfxParamSetHandle paramSet;
131 gEffectHost->getParamSet(pluginInstance, ¶mSet);
132
133 // get the parameter from the parameter set
134 OfxParamHandle param;
135 gParamHost->paramGetHandle(paramSet, kPointParam, ¶m, NULL);
136
137 // set it's value
138 return gParamHost->paramSetValue(param, str);
139 }
140
141 // The callback passed across the API do do custom parameter animation
142 static OfxStatus
customParamInterpFunction(OfxImageEffectHandle,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)143 customParamInterpFunction(OfxImageEffectHandle /*instance*/,
144 OfxPropertySetHandle inArgs,
145 OfxPropertySetHandle outArgs)
146 {
147 double x0, y0, x1, y1;
148 OfxStatus err;
149
150 const char *fromValue = NULL, *toValue = NULL;
151
152 // parse the custom param at the from value
153 gPropHost->propGetString(inArgs, kOfxParamPropCustomValue, 0, &fromValue);
154 if((err = parseCustomParam(fromValue, x0, y0)) != kOfxStatOK)
155 return err;
156
157 // parse the custom param at the to value
158 gPropHost->propGetString(inArgs, kOfxParamPropCustomValue, 1, &toValue);
159 if((err = parseCustomParam(toValue, x1, y1)) != kOfxStatOK)
160 return err;
161
162 // get the interp amount
163 double interp;
164 gPropHost->propGetDouble(inArgs, kOfxParamPropInterpolationAmount, 0, &interp);
165
166 // and lerp the values
167 double x = x0 + (x1 - x0) * interp;
168 double y = y0 + (y1 - y0) * interp;
169
170 // now encode the value and set it
171 char str[1024];
172 writeCustomParam(str, 1024, x, y);
173 gPropHost->propSetString(outArgs, kOfxParamPropCustomValue, 0, str);
174
175 return kOfxStatOK;
176 }
177
178 // plugin instance construction
179 static OfxStatus
createInstance(OfxImageEffectHandle)180 createInstance(OfxImageEffectHandle /*instance*/)
181 {
182 return kOfxStatOK;
183 }
184
185 // plugin instance destruction
186 static OfxStatus
destroyInstance(OfxImageEffectHandle)187 destroyInstance(OfxImageEffectHandle /*instance*/)
188 {
189 return kOfxStatOK;
190 }
191
192 static OfxStatus
isIdentity(OfxImageEffectHandle,OfxPropertySetHandle,OfxPropertySetHandle outArgs)193 isIdentity(OfxImageEffectHandle /*pluginInstance*/,
194 OfxPropertySetHandle /*inArgs*/,
195 OfxPropertySetHandle outArgs)
196 {
197 // set the property in the out args indicating which is the identity clip
198 gPropHost->propSetString(outArgs, kOfxPropName, 0, kOfxImageEffectSimpleSourceClipName);
199 return kOfxStatOK;
200 }
201
202 // the process code that the host sees
render(OfxImageEffectHandle,OfxPropertySetHandle,OfxPropertySetHandle)203 static OfxStatus render(OfxImageEffectHandle /*instance*/,
204 OfxPropertySetHandle /*inArgs*/,
205 OfxPropertySetHandle /*outArg*/)
206 {
207 // do nothing as this should never be called as isIdentity should always be trapped
208 return kOfxStatOK;
209 }
210
211 ////////////////////////////////////////////////////////////////////////////////
212 // the interaction routines
213 struct MyInteractData {
214 bool selected;
215 OfxParamHandle pointParam;
216
MyInteractDataMyInteractData217 explicit MyInteractData(OfxParamHandle pParam)
218 : selected(false)
219 , pointParam(pParam)
220 {
221 }
222 };
223
224 // get the interact data from an interact instance
225 static MyInteractData *
getInteractData(OfxInteractHandle interactInstance)226 getInteractData(OfxInteractHandle interactInstance)
227 {
228 void *dataV = ofxuGetInteractInstanceData(interactInstance);
229 return (MyInteractData *) dataV;
230 }
231
232 // creation of an interact instance
233 static OfxStatus
interactDescribe(OfxInteractHandle)234 interactDescribe(OfxInteractHandle /*interactDescriptor*/)
235 {
236 // and we are good
237 return kOfxStatOK;
238 }
239
240 // creation of an interact instance
241 static OfxStatus
interactCreateInstance(OfxImageEffectHandle pluginInstance,OfxInteractHandle interactInstance)242 interactCreateInstance(OfxImageEffectHandle pluginInstance,
243 OfxInteractHandle interactInstance)
244 {
245 // get the parameter set for this effect
246 OfxParamSetHandle paramSet;
247 gEffectHost->getParamSet(pluginInstance, ¶mSet);
248
249 // fetch a handle to the point param from the parameter set
250 OfxParamHandle pointParam;
251 gParamHost->paramGetHandle(paramSet, kPointParam, &pointParam, 0);
252
253 // make my interact's instance data
254 MyInteractData *data = new MyInteractData(pointParam);
255
256 // and set the interact's data pointer
257 ofxuSetInteractInstanceData(interactInstance, (void *) data);
258
259 OfxPropertySetHandle interactProps;
260 gInteractHost->interactGetPropertySet(interactInstance, &interactProps);
261
262 // slave this interact to the point param so redraws are triggered cleanly
263 gPropHost->propSetString(interactProps, kOfxInteractPropSlaveToParam, 0, kPointParam);
264
265 return kOfxStatOK;
266 }
267
268 // destruction of an interact instance
269 static OfxStatus
interactDestroyInstance(OfxImageEffectHandle,OfxInteractHandle interactInstance)270 interactDestroyInstance(OfxImageEffectHandle /*pluginInstance*/,
271 OfxInteractHandle interactInstance)
272 {
273 MyInteractData *data = getInteractData(interactInstance);
274 delete data;
275 return kOfxStatOK;
276 }
277
278 // size of the cross hair in screen pixels
279 #define kXHairSize 10
280
281 // draw an interact instance
282 static OfxStatus
interactDraw(OfxImageEffectHandle pluginInstance,OfxInteractHandle interactInstance,OfxPropertySetHandle drawArgs)283 interactDraw(OfxImageEffectHandle pluginInstance,
284 OfxInteractHandle interactInstance,
285 OfxPropertySetHandle drawArgs)
286 {
287 OfxStatus err;
288 // get my private interact data
289 MyInteractData *data = getInteractData(interactInstance);
290
291 // get the project size
292 OfxPointD projSize = {1., 1.}, projOffset = {0., 0.};
293 ofxuGetProjectSetup(pluginInstance, projSize, projOffset);
294
295 // get the size of a pixel in the current projection
296 double pixelScale[2];
297 ofxuGetInteractPixelScale(drawArgs, pixelScale);
298
299 // get my param's value
300 double x, y;
301 if((err = getCustomParam(pluginInstance, x, y)) != kOfxStatOK)
302 return err;
303
304 // scale it up to the project size as it is normalised
305 x = projOffset.x + x * projSize.x;
306 y = projOffset.y + y * projSize.y;
307
308 // make the xhair a constant size on screen by scaling by the pixel scale
309 float dx = kXHairSize * pixelScale[0];
310 float dy = kXHairSize * pixelScale[1];
311
312 // if the we have selected the Xhair, draw it highlit
313 if(data->selected)
314 glColor3f(1, 1, 1);
315 else
316 glColor3f(1, 0, 0);
317
318 // Draw a cross hair, the current coordinate system aligns with the image plane.
319 glPushMatrix();
320
321 glTranslated(x, y, 0);
322
323 glBegin(GL_LINES);
324
325 glVertex2f(-dx, 0);
326 glVertex2f(dx, 0);
327
328 glVertex2f(0, -dy);
329 glVertex2f(0, dy);
330
331 glEnd();
332
333
334 glPopMatrix();
335
336 return kOfxStatOK;
337 }
338
339 // function reacting to pen motion
340 static OfxStatus
interactPenMotion(OfxImageEffectHandle pluginInstance,OfxInteractHandle interactInstance,OfxPropertySetHandle inArgs)341 interactPenMotion(OfxImageEffectHandle pluginInstance,
342 OfxInteractHandle interactInstance,
343 OfxPropertySetHandle inArgs)
344 {
345 // get my data handle
346 MyInteractData *data = getInteractData(interactInstance);
347
348 // Have we grabbed on a pen down already?
349 if(data->selected) {
350 // get the project size as we are normalising to this
351 OfxPointD projSize = {1., 1.}, projOffset = {0., 0.};
352 ofxuGetProjectSetup(pluginInstance, projSize, projOffset);
353
354 // get the pen position and normalise that
355 OfxPointD penPos = {0., 0.};
356 gPropHost->propGetDoubleN(inArgs, kOfxInteractPropPenPosition, 2, &penPos.x);
357 penPos.x = (penPos.x - projOffset.x)/projSize.x;
358 penPos.y = (penPos.y - projOffset.y)/projSize.y;
359
360 // set the value of the 'point' param
361 setCustomParam(pluginInstance, penPos.x, penPos.y);
362 return kOfxStatOK;
363 }
364 return kOfxStatReplyDefault;
365 }
366
367 static OfxStatus
interactPenDown(OfxImageEffectHandle pluginInstance,OfxInteractHandle interactInstance,OfxPropertySetHandle inArgs)368 interactPenDown(OfxImageEffectHandle pluginInstance,
369 OfxInteractHandle interactInstance,
370 OfxPropertySetHandle inArgs)
371 {
372 // get my data handle
373 MyInteractData *data = getInteractData(interactInstance);
374
375 // get the project size as we are normalising to this
376 OfxPointD projSize = {1., 1.}, projOffset = {0., 0.};
377 ofxuGetProjectSetup(pluginInstance, projSize, projOffset);
378
379 // get the point param's value
380 double x, y;
381 OfxStatus stat = getCustomParam(pluginInstance, x, y);
382 if (stat != kOfxStatOK) {
383 return stat;
384 }
385
386 // scale it up to the project size as it is a normalised spatial parameter
387 x = projOffset.x + x * projSize.x;
388 y = projOffset.y + y * projSize.y;
389
390 // get the size of a pixel on screen
391 double pixelScale[2];
392 ofxuGetInteractPixelScale(inArgs, pixelScale);
393
394 // see if the pen is within 5 screen pixels of the point, in which case, select it
395 double penPos[2];
396 gPropHost->propGetDoubleN(inArgs, kOfxInteractPropPenPosition, 2, penPos);
397 if(fabs(x - penPos[0]) < 5 * pixelScale[0] && fabs(y - penPos[1]) < 5 * pixelScale[1]) {
398 data->selected = true;
399 return kOfxStatOK;
400 }
401 return kOfxStatReplyDefault;
402 }
403
404 static OfxStatus
interactPenUp(OfxImageEffectHandle,OfxInteractHandle interactInstance,OfxPropertySetHandle)405 interactPenUp(OfxImageEffectHandle /*pluginInstance*/,
406 OfxInteractHandle interactInstance,
407 OfxPropertySetHandle /*inArgs*/)
408 {
409 // get my data handle
410 MyInteractData *data = getInteractData(interactInstance);
411
412 if(data->selected) {
413 // pen's gone up, deselect
414 data->selected = false;
415 return kOfxStatOK;
416 }
417 return kOfxStatReplyDefault;
418 }
419
420 ////////////////////////////////////////////////////////////////////////////////
421 // the entry point for the overlay
422 static OfxStatus
overlayMain(const char * action,const void * handle,OfxPropertySetHandle inArgs,OfxPropertySetHandle)423 overlayMain(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle /*outArgs*/)
424 {
425 OfxInteractHandle interact = (OfxInteractHandle ) handle;
426
427 OfxPropertySetHandle props;
428 gInteractHost->interactGetPropertySet(interact, &props);
429
430 if(strcmp(action, kOfxActionDescribe) == 0) {
431 return interactDescribe(interact);
432 }
433 else {
434 // in which case handle is the interact instance
435
436 // fetch the effect instance from the interact
437 OfxImageEffectHandle pluginInstance;
438 gPropHost->propGetPointer(props, kOfxPropEffectInstance, 0, (void **) &pluginInstance);
439
440 if(strcmp(action, kOfxActionCreateInstance) == 0) {
441 return interactCreateInstance(pluginInstance, interact);
442 }
443 else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
444 return interactDestroyInstance(pluginInstance, interact);
445 }
446 else if(strcmp(action, kOfxInteractActionDraw) == 0) {
447 return interactDraw(pluginInstance, interact, inArgs);
448 }
449 else if(strcmp(action, kOfxInteractActionPenMotion) == 0) {
450 return interactPenMotion(pluginInstance, interact, inArgs);
451 }
452 else if(strcmp(action, kOfxInteractActionPenDown) == 0) {
453 return interactPenDown(pluginInstance, interact, inArgs);
454 }
455 else if(strcmp(action, kOfxInteractActionPenUp) == 0) {
456 return interactPenUp(pluginInstance, interact, inArgs);
457 }
458 return kOfxStatReplyDefault;
459 }
460 }
461
462
463 ////////////////////////////////////////////////////////////////////////////////
464 // the plugin's description routine
465 static OfxStatus
describe(OfxImageEffectHandle effect)466 describe(OfxImageEffectHandle effect)
467 {
468 // fetch the host APIs
469 OfxStatus stat;
470 if((stat = ofxuFetchHostSuites()) != kOfxStatOK)
471 return stat;
472
473 // see if the host supports overlays and custom params and custom param animation
474 int supportsOverlays;
475 gPropHost->propGetInt(gHost->host, kOfxImageEffectPropSupportsOverlays, 0, &supportsOverlays);
476 if(supportsOverlays == 0)
477 return kOfxStatErrMissingHostFeature;
478
479 // get the property handle for the plugin
480 OfxPropertySetHandle effectProps;
481 gEffectHost->getPropertySet(effect, &effectProps);
482
483 // set the bit depths the plugin can handle
484 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 0, kOfxBitDepthByte);
485 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 1, kOfxBitDepthShort);
486 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 2, kOfxBitDepthFloat);
487
488 // define the plugin to the host
489 gPropHost->propSetString(effectProps, kOfxPropLabel, 0, "OFX Custom Param Example");
490 gPropHost->propSetString(effectProps, kOfxImageEffectPluginPropGrouping, 0, "OFX Example");
491
492 // define the contexts we can be used in
493 gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedContexts, 0, kOfxImageEffectContextFilter);
494
495 // set the property that is the overlay's main entry point for the plugin
496 gPropHost->propSetPointer(effectProps, kOfxImageEffectPluginPropOverlayInteractV1, 0, (void *) overlayMain);
497
498 return kOfxStatOK;
499 }
500
501 static OfxStatus
describeInContext(OfxImageEffectHandle effect,OfxPropertySetHandle)502 describeInContext(OfxImageEffectHandle effect, OfxPropertySetHandle /*inArgs*/)
503 {
504 // define the mandated single source clip
505 OfxPropertySetHandle props;
506 gEffectHost->clipDefine(effect, kOfxImageEffectSimpleSourceClipName, &props);
507 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
508 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
509
510 // define the output clip
511 gEffectHost->clipDefine(effect, kOfxImageEffectOutputClipName, &props);
512 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
513 gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
514
515 // fetch the parameter set from the effect
516 OfxParamSetHandle paramSet;
517 gEffectHost->getParamSet(effect, ¶mSet);
518
519 // Make a custom parameter
520 gParamHost->paramDefine(paramSet, kOfxParamTypeCustom, kPointParam, &props);
521 gPropHost->propSetString(props, kOfxParamPropDefault, 0, "0.5 0.5");
522 gPropHost->propSetString(props, kOfxParamPropScriptName, 0, "point");
523 gPropHost->propSetString(props, kOfxParamPropHint, 0, "Custom point attached to overlay crosshair");
524 gPropHost->propSetString(props, kOfxPropLabel, 0, "Point");
525
526 // set the custom anim callback of the host supports custom animation
527 int supportsCustomAnim;
528 gPropHost->propGetInt(gHost->host, kOfxParamHostPropSupportsCustomAnimation, 0, &supportsCustomAnim);
529 if(supportsCustomAnim) {
530 gPropHost->propSetInt(props, kOfxParamPropAnimates, 0, true);
531 gPropHost->propSetPointer(props, kOfxParamPropCustomInterpCallbackV1, 0, (void *) customParamInterpFunction);
532 }
533 else {
534 gPropHost->propSetInt(props, kOfxParamPropAnimates, 0, false);
535 }
536
537 return kOfxStatOK;
538 }
539
540 ////////////////////////////////////////////////////////////////////////////////
541 // The main function
542 static OfxStatus
pluginMain(const char * action,const void * handle,OfxPropertySetHandle inArgs,OfxPropertySetHandle outArgs)543 pluginMain(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
544 {
545 try {
546 // cast to appropriate type
547 OfxImageEffectHandle effect = (OfxImageEffectHandle) handle;
548
549 if(strcmp(action, kOfxActionDescribe) == 0) {
550 return describe(effect);
551 }
552 else if(strcmp(action, kOfxImageEffectActionDescribeInContext) == 0) {
553 return describeInContext(effect, inArgs);
554 }
555 else if(strcmp(action, kOfxActionCreateInstance) == 0) {
556 return createInstance(effect);
557 }
558 else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
559 return destroyInstance(effect);
560 }
561 else if(strcmp(action, kOfxImageEffectActionIsIdentity) == 0) {
562 return isIdentity(effect, inArgs, outArgs);
563 }
564 else if(strcmp(action, kOfxImageEffectActionRender) == 0) {
565 return render(effect, inArgs, outArgs);
566 }
567 } catch (std::bad_alloc) {
568 // catch memory
569 //std::cout << "OFX Plugin Memory error." << std::endl;
570 return kOfxStatErrMemory;
571 } catch ( const std::exception& e ) {
572 // standard exceptions
573 //std::cout << "OFX Plugin error: " << e.what() << std::endl;
574 return kOfxStatErrUnknown;
575 } catch (int err) {
576 // ho hum, gone wrong somehow
577 return err;
578 } catch ( ... ) {
579 // everything else
580 //std::cout << "OFX Plugin error" << std::endl;
581 return kOfxStatErrUnknown;
582 }
583
584 // other actions to take the default value
585 return kOfxStatReplyDefault;
586 }
587
588 // function to set the host structure
589 static void
setHostFunc(OfxHost * hostStruct)590 setHostFunc(OfxHost *hostStruct)
591 {
592 gHost = hostStruct;
593 }
594
595 ////////////////////////////////////////////////////////////////////////////////
596 // the plugin struct
597 static OfxPlugin basicPlugin =
598 {
599 kOfxImageEffectPluginApi,
600 1,
601 "uk.co.thefoundry.CustomParamPlugin",
602 1,
603 0,
604 setHostFunc,
605 pluginMain
606 };
607
608 // the two mandated functions
609 EXPORT OfxPlugin *
OfxGetPlugin(int nth)610 OfxGetPlugin(int nth)
611 {
612 if(nth == 0)
613 return &basicPlugin;
614 return 0;
615 }
616
617 EXPORT int
OfxGetNumberOfPlugins(void)618 OfxGetNumberOfPlugins(void)
619 {
620 return 1;
621 }
622