1 /* 2 Software License : 3 4 Copyright (c) 2007-2009, 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 #include <math.h> 31 32 // ofx 33 #include "ofxCore.h" 34 #include "ofxImageEffect.h" 35 #ifdef OFX_SUPPORTS_DIALOG 36 #include "ofxDialog.h" 37 #endif 38 #ifdef OFX_EXTENSIONS_VEGAS 39 #include "ofxSonyVegas.h" 40 #endif 41 #ifdef OFX_EXTENSIONS_TUTTLE 42 #include "tuttle/ofxReadWrite.h" 43 #endif 44 #ifdef OFX_EXTENSIONS_NUKE 45 #include "nuke/fnOfxExtensions.h" 46 #endif 47 #ifdef OFX_EXTENSIONS_NATRON 48 #include "ofxNatron.h" 49 #endif 50 51 // ofx host 52 #include "ofxhBinary.h" 53 #include "ofxhPropertySuite.h" 54 #include "ofxhClip.h" 55 #include "ofxhParam.h" 56 #include "ofxhMemory.h" 57 #include "ofxhImageEffect.h" 58 #include "ofxhPluginAPICache.h" 59 #include "ofxhPluginCache.h" 60 #include "ofxhHost.h" 61 #include "ofxhImageEffectAPI.h" 62 #include "ofxhUtilities.h" 63 #ifdef OFX_SUPPORTS_PARAMETRIC 64 #include "ofxhParametricParam.h" 65 #endif 66 #ifdef OFX_SUPPORTS_OPENGLRENDER 67 #include "ofxOpenGLRender.h" 68 #endif 69 #include "ofxOld.h" // old plugins may rely on deprecated properties being present 70 71 #include <string.h> 72 #include <stdarg.h> 73 74 namespace OFX { 75 76 namespace Host { 77 78 namespace ImageEffect { 79 80 /// properties common on an effect and a descriptor 81 static const Property::PropSpec effectDescriptorStuff[] = { 82 /* name type dim. r/o default value */ 83 { kOfxPropType, Property::eString, 1, true, kOfxTypeImageEffect }, 84 { kOfxPropLabel, Property::eString, 1, false, "" }, 85 { kOfxPropShortLabel, Property::eString, 1, false, "" }, 86 { kOfxPropLongLabel, Property::eString, 1, false, "" }, 87 { kOfxPropVersion, Property::eInt, 0, false, "0" }, 88 { kOfxPropVersionLabel, Property::eString, 1, false, "" }, 89 { kOfxPropPluginDescription, Property::eString, 1, false, "" }, 90 { kOfxImageEffectPropSupportedContexts, Property::eString, 0, false, "" }, 91 { kOfxImageEffectPluginPropGrouping, Property::eString, 1, false, "" }, 92 { kOfxImageEffectPluginPropSingleInstance, Property::eInt, 1, false, "0" }, 93 { kOfxImageEffectPluginRenderThreadSafety, Property::eString, 1, false, kOfxImageEffectRenderInstanceSafe }, 94 { kOfxImageEffectPluginPropHostFrameThreading, Property::eInt, 1, false, "1" }, 95 { kOfxImageEffectPluginPropOverlayInteractV1, Property::ePointer, 1, false, NULL }, 96 { kOfxImageEffectPropSupportsMultiResolution, Property::eInt, 1, false, "1" } , 97 { kOfxImageEffectPropSupportsTiles, Property::eInt, 1, false, "1" }, 98 { kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, false, "0" }, 99 { kOfxImageEffectPropSupportedPixelDepths, Property::eString, 0, false, "" }, 100 { kOfxImageEffectPluginPropFieldRenderTwiceAlways, Property::eInt, 1, false, "1" } , 101 { kOfxImageEffectPropSupportsMultipleClipDepths, Property::eInt, 1, false, "0" }, 102 { kOfxImageEffectPropSupportsMultipleClipPARs, Property::eInt, 1, false, "0" }, 103 { kOfxImageEffectPropClipPreferencesSlaveParam, Property::eString, 0, false, "" }, 104 { kOfxImageEffectInstancePropSequentialRender, Property::eInt, 1, false, "0" }, 105 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, false, "0" }, 106 { kOfxPluginPropFilePath, Property::eString, 1, true, ""}, 107 #ifdef OFX_SUPPORTS_OPENGLRENDER 108 { kOfxImageEffectPropOpenGLRenderSupported, Property::eString, 1, false, "false"}, // OFX 1.3 109 { kOfxOpenGLPropPixelDepth, Property::eString, 0, false, "" }, 110 #endif 111 #ifdef OFX_EXTENSIONS_RESOLVE 112 { kOfxImageEffectPropOpenCLRenderSupported, Property::eString, 1, false, "false"}, 113 { kOfxImageEffectPropCudaRenderSupported, Property::eString, 1, false, "false" }, 114 #endif 115 #ifdef OFX_EXTENSIONS_NUKE 116 { kFnOfxImageEffectPropMultiPlanar, Property::eInt, 1, false, "0" }, 117 { kFnOfxImageEffectPropPassThroughComponents, Property::eInt, 1, false, "0" }, 118 { kFnOfxImageEffectPropViewAware, Property::eInt, 1, false, "0" }, 119 { kFnOfxImageEffectPropViewInvariance, Property::eInt, 1, false, "0" }, 120 { kFnOfxImageEffectCanTransform, Property::eInt, 1, false, "0" }, 121 //{ ".length", Property::eDouble, 1, false, ""}, // Unknown Nuke property 122 #endif 123 #ifdef OFX_EXTENSIONS_TUTTLE 124 { kTuttleOfxImageEffectPropSupportedExtensions, Property::eString, 0, false, "" }, 125 { kTuttleOfxImageEffectPropEvaluation, Property::eDouble, 1, false, "-1" }, 126 #endif 127 #ifdef OFX_EXTENSIONS_VEGAS 128 { kOfxProbPluginVegasPresetThumbnail, Property::eString, 0, false, "" }, 129 { kOfxImageEffectPropVegasUpliftGUID, Property::eString, 0, false, "" }, 130 { kOfxImageEffectPropHelpFile, Property::eString, 1, false, "" }, 131 { kOfxImageEffectPropHelpContextID, Property::eInt, 1, false, "0" }, 132 #endif 133 #ifdef OFX_EXTENSIONS_NATRON 134 { kNatronOfxImageEffectPluginUsesMultipleThread, Property::eInt, 1, true, "0" }, 135 { kNatronOfxImageEffectPropChannelSelector, Property::eString, 1, true, kOfxImageComponentRGBA }, 136 { kNatronOfxImageEffectPropHostMasking, Property::eInt, 1, true, "0" }, 137 { kNatronOfxImageEffectPropHostMixing, Property::eInt, 1, true, "0" }, 138 { kNatronOfxImageEffectPropDeprecated, Property::eInt, 1, true, "0" }, 139 { kNatronOfxImageEffectPropProjectId, Property::eString, 1, true, "" }, 140 { kNatronOfxImageEffectPropGroupId, Property::eString, 1, true, "" }, 141 { kNatronOfxImageEffectPropInstanceId, Property::eString, 1, true, "" }, 142 { kNatronOfxPropDescriptionIsMarkdown, Property::eInt, 1, false, "0" }, 143 { kNatronOfxImageEffectSelectionRectangle, Property::eDouble, 4, true, "" }, 144 { kNatronOfxImageEffectPropDefaultCursors, Property::eString, 0, true, "" }, 145 { kNatronOfxImageEffectPropInViewerContextParamsOrder, Property::eString, 0, false, "" }, 146 { kNatronOfxImageEffectPropInViewerContextDefaultShortcuts, Property::eString, 0, true, "" }, 147 { kNatronOfxImageEffectPropInViewerContextShortcutSymbol, Property::eInt, 0, true, "" }, 148 { kNatronOfxImageEffectPropInViewerContextShortcutHasControlModifier, Property::eInt, 0, true, "" }, 149 { kNatronOfxImageEffectPropInViewerContextShortcutHasShiftModifier, Property::eInt, 0, true, "" }, 150 { kNatronOfxImageEffectPropInViewerContextShortcutHasAltModifier, Property::eInt, 0, true, "" }, 151 { kNatronOfxImageEffectPropInViewerContextShortcutHasMetaModifier, Property::eInt, 0, true, "" }, 152 { kNatronOfxImageEffectPropInViewerContextShortcutHasKeypadModifier, Property::eInt, 0, true, "" }, 153 { kNatronOfxPropNativeOverlays, Property::eString, 0, false, ""}, 154 { kOfxImageEffectPropCanDistort, Property::eInt, 1, true, "0" }, 155 { kOfxImageEffectPropRenderAllPlanes, Property::eInt, 1, true, "0"}, 156 #endif 157 Property::propSpecEnd 158 }; 159 160 // 161 // Base 162 // 163 Base(const Property::Set & set)164 Base::Base(const Property::Set &set) 165 : _properties(set) 166 {} 167 Base(const Property::PropSpec * propSpec)168 Base::Base(const Property::PropSpec * propSpec) 169 : _properties(propSpec) 170 {} 171 ~Base()172 Base::~Base() {} 173 174 /// obtain a handle on this for passing to the C api getHandle() const175 OfxImageEffectHandle Base::getHandle() const { 176 return (OfxImageEffectHandle)this; 177 } 178 179 /// get the properties set getProps()180 Property::Set &Base::getProps() { 181 return _properties; 182 } 183 184 /// get the properties set, const version getProps() const185 const Property::Set &Base::getProps() const { 186 return _properties; 187 } 188 189 /// name of the clip getShortLabel() const190 const std::string &Base::getShortLabel() const 191 { 192 const std::string &s = _properties.getStringProperty(kOfxPropShortLabel); 193 if(s == "") { 194 const std::string &s2 = _properties.getStringProperty(kOfxPropLabel); 195 if(s2 == "") { 196 return _properties.getStringProperty(kOfxPropName); 197 } 198 } 199 return s; 200 } 201 202 /// name of the clip getLabel() const203 const std::string &Base::getLabel() const 204 { 205 const std::string &s = _properties.getStringProperty(kOfxPropLabel); 206 if(s == "") { 207 return _properties.getStringProperty(kOfxPropName); 208 } 209 return s; 210 } 211 212 /// name of the clip getLongLabel() const213 const std::string &Base::getLongLabel() const 214 { 215 const std::string &s = _properties.getStringProperty(kOfxPropLongLabel); 216 if(s == "") { 217 const std::string &s2 = _properties.getStringProperty(kOfxPropLabel); 218 if(s2 == "") { 219 return _properties.getStringProperty(kOfxPropName); 220 } 221 } 222 return s; 223 } 224 225 /// is the given context supported isContextSupported(const std::string & s) const226 bool Base::isContextSupported(const std::string &s) const 227 { 228 return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedContexts, s) != -1; 229 } 230 231 /// what is the name of the group the plug-in belongs to getPluginGrouping() const232 const std::string &Base::getPluginGrouping() const 233 { 234 return _properties.getStringProperty(kOfxImageEffectPluginPropGrouping); 235 } 236 237 /// is the effect single instance isSingleInstance() const238 bool Base::isSingleInstance() const 239 { 240 return _properties.getIntProperty(kOfxImageEffectPluginPropSingleInstance) != 0; 241 } 242 243 /// what is the thread safety on this effect getRenderThreadSafety() const244 const std::string &Base::getRenderThreadSafety() const 245 { 246 return _properties.getStringProperty(kOfxImageEffectPluginRenderThreadSafety); 247 } 248 249 #ifdef OFX_EXTENSIONS_NATRON getUsesMultiThreading() const250 bool Base::getUsesMultiThreading() const 251 { 252 return _properties.getIntProperty(kNatronOfxImageEffectPluginUsesMultipleThread) != 0; 253 } 254 #endif 255 256 /// should the host attempt to managed multi-threaded rendering if it can 257 /// via tiling or some such getHostFrameThreading() const258 bool Base::getHostFrameThreading() const 259 { 260 return _properties.getIntProperty(kOfxImageEffectPluginPropHostFrameThreading) != 0; 261 } 262 263 /// get the overlay interact main entry if it exists getOverlayInteractMainEntry() const264 OfxPluginEntryPoint *Base::getOverlayInteractMainEntry() const 265 { 266 return (OfxPluginEntryPoint *)(_properties.getPointerProperty(kOfxImageEffectPluginPropOverlayInteractV1)); 267 } 268 269 /// does the effect support images of differing sizes supportsMultiResolution() const270 bool Base::supportsMultiResolution() const 271 { 272 return _properties.getIntProperty(kOfxImageEffectPropSupportsMultiResolution) != 0; 273 } 274 275 /// does the effect support tiled rendering supportsTiles() const276 bool Base::supportsTiles() const 277 { 278 return _properties.getIntProperty(kOfxImageEffectPropSupportsTiles) != 0; 279 } 280 281 /// does this effect need random temporal access temporalAccess() const282 bool Base::temporalAccess() const 283 { 284 return _properties.getIntProperty(kOfxImageEffectPropTemporalClipAccess) != 0; 285 } 286 287 /// is the given RGBA/A pixel depth supported by the effect isPixelDepthSupported(const std::string & s) const288 bool Base::isPixelDepthSupported(const std::string &s) const 289 { 290 return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedPixelDepths, s) != -1; 291 } 292 293 #ifdef OFX_SUPPORTS_OPENGLRENDER 294 /// is the given RGBA/A OpenGL pixel depth supported by the effect isOpenGLPixelDepthSupported(const std::string & s) const295 bool Base::isOpenGLPixelDepthSupported(const std::string &s) const 296 { 297 // if property is empty, all depths are supported 298 return _properties.getDimension(kOfxOpenGLPropPixelDepth) == 0 || _properties.findStringPropValueIndex(kOfxOpenGLPropPixelDepth, s) != -1; 299 } 300 #endif 301 302 /// when field rendering, does the effect need to be called 303 /// twice to render a frame in all Base::circumstances (with different fields) fieldRenderTwiceAlways() const304 bool Base::fieldRenderTwiceAlways() const 305 { 306 return _properties.getIntProperty(kOfxImageEffectPluginPropFieldRenderTwiceAlways) != 0; 307 } 308 309 /// does the effect support multiple clip depths supportsMultipleClipDepths() const310 bool Base::supportsMultipleClipDepths() const 311 { 312 return _properties.getIntProperty(kOfxImageEffectPropSupportsMultipleClipDepths) != 0; 313 } 314 315 /// does the effect support multiple clip pixel aspect ratios supportsMultipleClipPARs() const316 bool Base::supportsMultipleClipPARs() const 317 { 318 return _properties.getIntProperty(kOfxImageEffectPropSupportsMultipleClipPARs) != 0; 319 } 320 321 /// does changing the named param re-tigger a clip preferences action isClipPreferencesSlaveParam(const std::string & s) const322 bool Base::isClipPreferencesSlaveParam(const std::string &s) const 323 { 324 return _properties.findStringPropValueIndex(kOfxImageEffectPropClipPreferencesSlaveParam, s) != -1; 325 } 326 327 328 /// does the effect require sequential render requiresSequentialRender() const329 bool Base::requiresSequentialRender() const 330 { 331 return _properties.getIntProperty(kOfxImageEffectInstancePropSequentialRender) == 1; 332 } 333 334 /// does the effect prefer sequential render prefersSequentialRender() const335 bool Base::prefersSequentialRender() const 336 { 337 return _properties.getIntProperty(kOfxImageEffectInstancePropSequentialRender) != 0; 338 } 339 340 /// does the effect support render quality supportsRenderQuality() const341 bool Base::supportsRenderQuality() const 342 { 343 return _properties.getIntProperty(kOfxImageEffectPropRenderQualityDraft) != 0; 344 } 345 346 #ifdef OFX_EXTENSIONS_NUKE 347 /// does this effect handle transform effects canTransform() const348 bool Base::canTransform() const 349 { 350 return _properties.getIntProperty(kFnOfxImageEffectCanTransform) != 0; 351 } 352 isMultiPlanar() const353 bool Base::isMultiPlanar() const 354 { 355 return _properties.getIntProperty(kFnOfxImageEffectPropMultiPlanar) != 0; 356 } 357 isHostMaskingEnabled() const358 bool Base::isHostMaskingEnabled() const 359 { 360 return _properties.getIntProperty(kNatronOfxImageEffectPropHostMasking) != 0; 361 } 362 isHostMixingEnabled() const363 bool Base::isHostMixingEnabled() const 364 { 365 return _properties.getIntProperty(kNatronOfxImageEffectPropHostMixing) != 0; 366 } 367 getPassThroughForNonRenderedPlanes() const368 Base::OfxPassThroughLevelEnum Base::getPassThroughForNonRenderedPlanes() const 369 { 370 371 int p = _properties.getIntProperty(kFnOfxImageEffectPropPassThroughComponents); 372 if (p == 2) { 373 return Base::ePassThroughLevelEnumRenderAllRequestedPlanes; 374 } 375 if (!isMultiPlanar()) { 376 return Base::ePassThroughLevelEnumPassThroughAllNonRenderedPlanes; 377 } 378 if (p == 0) { 379 return Base::ePassThroughLevelEnumBlockAllNonRenderedPlanes; 380 } else if (p == 1) { 381 return Base::ePassThroughLevelEnumPassThroughAllNonRenderedPlanes; 382 } else { 383 return Base::ePassThroughLevelEnumPassThroughAllNonRenderedPlanes; 384 } 385 } 386 isViewAware() const387 bool Base::isViewAware() const 388 { 389 return _properties.getIntProperty(kFnOfxImageEffectPropViewAware) != 0; 390 } 391 getViewInvariance() const392 int Base::getViewInvariance() const 393 { 394 return _properties.getIntProperty(kFnOfxImageEffectPropViewInvariance); 395 } 396 #endif 397 398 #ifdef OFX_EXTENSIONS_NATRON canDistort() const399 bool Base::canDistort() const 400 { 401 return _properties.getIntProperty(kOfxImageEffectPropCanDistort) != 0; 402 } 403 404 /// does this effect handle transform effects isDeprecated() const405 bool Base::isDeprecated() const 406 { 407 return _properties.getIntProperty(kNatronOfxImageEffectPropDeprecated) != 0; 408 } 409 isPluginDescriptionInMarkdown() const410 bool Base::isPluginDescriptionInMarkdown() const 411 { 412 return _properties.getIntProperty(kNatronOfxPropDescriptionIsMarkdown) != 0; 413 } 414 getPluginDefaultShortcuts(std::list<PluginShortcut> * shortcuts) const415 void Base::getPluginDefaultShortcuts(std::list<PluginShortcut>* shortcuts) const 416 { 417 if (!shortcuts) { 418 return; 419 } 420 const int nIds = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextDefaultShortcuts); 421 const int nSyms = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutSymbol); 422 const int nCtrl = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutHasControlModifier); 423 const int nShift = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutHasShiftModifier); 424 const int nAlt = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutHasAltModifier); 425 const int nMeta = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutHasMetaModifier); 426 const int nKeypad = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextShortcutHasKeypadModifier); 427 428 // Invalid properties 429 if (nIds != nSyms || nIds != nCtrl || nIds != nShift || nIds != nAlt || nIds != nMeta || nIds != nKeypad) { 430 return; 431 } 432 433 for (int i = 0; i < nIds; ++i) { 434 PluginShortcut p; 435 p.shortcutID = _properties.getStringProperty(kNatronOfxImageEffectPropInViewerContextDefaultShortcuts, i); 436 p.symbol = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutSymbol, i); 437 p.hasCtrlModifier = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutHasControlModifier, i); 438 p.hasShiftModifier = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutHasShiftModifier, i); 439 p.hasAltModifier = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutHasAltModifier, i); 440 p.hasMetaModifier = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutHasMetaModifier, i); 441 p.hasKeypadModifier = _properties.getIntProperty(kNatronOfxImageEffectPropInViewerContextShortcutHasKeypadModifier, i); 442 shortcuts->push_back(p); 443 } 444 445 } 446 447 // Get a list of the parameters name that are to be displayed in the viewport getInViewportParametersName(std::list<std::string> * parameterNames) const448 void Base::getInViewportParametersName(std::list<std::string>* parameterNames) const 449 { 450 if (!parameterNames) { 451 return; 452 } 453 const int nItems = _properties.getDimension(kNatronOfxImageEffectPropInViewerContextParamsOrder); 454 for (int i = 0; i < nItems; ++i) { 455 std::string paramName = _properties.getStringProperty(kNatronOfxImageEffectPropInViewerContextParamsOrder, i); 456 parameterNames->push_back(paramName); 457 } 458 } 459 460 // Get a list of the cursors used by this plug-in getDefaultCursors(std::list<std::string> * cursors) const461 void Base::getDefaultCursors(std::list<std::string>* cursors) const 462 { 463 if (!cursors) { 464 return; 465 } 466 const int nItems = _properties.getDimension(kNatronOfxImageEffectPropDefaultCursors); 467 for (int i = 0; i < nItems; ++i) { 468 std::string cursor = _properties.getStringProperty(kNatronOfxImageEffectPropDefaultCursors, i); 469 cursors->push_back(cursor); 470 } 471 } 472 473 // Update the selection rectangle property setSelectionRectangleState(double x1,double y1,double x2,double y2)474 void Base::setSelectionRectangleState(double x1, double y1, double x2, double y2) 475 { 476 _properties.setDoubleProperty(kNatronOfxImageEffectSelectionRectangle, x1, 0); 477 _properties.setDoubleProperty(kNatronOfxImageEffectSelectionRectangle, y1, 1); 478 _properties.setDoubleProperty(kNatronOfxImageEffectSelectionRectangle, x2, 2); 479 _properties.setDoubleProperty(kNatronOfxImageEffectSelectionRectangle, y2, 3); 480 } 481 482 #endif // OFX_EXTENSIONS_NATRON 483 //////////////////////////////////////////////////////////////////////////////// 484 // descriptor 485 Descriptor(Plugin * plug)486 Descriptor::Descriptor(Plugin *plug) 487 : Base(effectDescriptorStuff) 488 , _plugin(plug) 489 { 490 _properties.setStringProperty(kOfxPluginPropFilePath, plug->getBinary()->getBundlePath()); 491 gImageEffectHost->initDescriptor(this); 492 } 493 Descriptor(const Descriptor & other,Plugin * plug)494 Descriptor::Descriptor(const Descriptor &other, Plugin *plug) 495 : Base(other._properties) 496 , _plugin(plug) 497 { 498 _properties.setStringProperty(kOfxPluginPropFilePath, plug->getBinary()->getBundlePath()); 499 gImageEffectHost->initDescriptor(this); 500 } 501 Descriptor(const std::string & bundlePath,Plugin * plug)502 Descriptor::Descriptor(const std::string &bundlePath, Plugin *plug) 503 : Base(effectDescriptorStuff) 504 , _plugin(plug) 505 { 506 _properties.setStringProperty(kOfxPluginPropFilePath, bundlePath); 507 gImageEffectHost->initDescriptor(this); 508 } 509 ~Descriptor()510 Descriptor::~Descriptor() 511 { 512 for(std::map<std::string, ClipDescriptor*>::iterator it = _clips.begin(); it != _clips.end(); ++it) 513 delete it->second; 514 _clips.clear(); 515 } 516 517 518 /// create a new clip and add this to the clip map defineClip(const std::string & name)519 ClipDescriptor *Descriptor::defineClip(const std::string &name) { 520 ClipDescriptor *c = new ClipDescriptor(name); 521 _clips[name] = c; 522 _clipsByOrder.push_back(c); 523 return c; 524 } 525 526 /// implemented for Param::SetDescriptor getParamSetProps()527 Property::Set &Descriptor::getParamSetProps() 528 { 529 return _properties; 530 } 531 532 /// get the interact description, this will also call describe on the interact getOverlayDescriptor(int bitDepthPerComponent,bool hasAlpha)533 Interact::Descriptor &Descriptor::getOverlayDescriptor(int bitDepthPerComponent, bool hasAlpha) 534 { 535 if(_overlayDescriptor.getState() == Interact::eUninitialised) { 536 // OK, we need to describe it, set the entry point and describe away 537 _overlayDescriptor.setEntryPoint(getOverlayInteractMainEntry()); 538 _overlayDescriptor.describe(bitDepthPerComponent, hasAlpha); 539 } 540 541 return _overlayDescriptor; 542 } 543 544 /// get the clips getClips() const545 const std::map<std::string, ClipDescriptor*> &Descriptor::getClips() const { 546 return _clips; 547 } 548 addClip(const std::string & name,ClipDescriptor * clip)549 void Descriptor::addClip(const std::string &name, ClipDescriptor *clip) { 550 _clips[name] = clip; 551 _clipsByOrder.push_back(clip); 552 } 553 554 // 555 // Instance 556 // 557 558 static const Property::PropSpec effectInstanceStuff[] = { 559 /* name type dim. r/o default value */ 560 { kOfxImageEffectPropContext, Property::eString, 1, true, "" }, 561 { kOfxPropInstanceData, Property::ePointer, 1, false, NULL }, 562 { kOfxImageEffectPropPluginHandle, Property::ePointer, 1, false, NULL }, 563 { kOfxImageEffectPropProjectSize, Property::eDouble, 2, true, "0" }, 564 { kOfxImageEffectPropProjectOffset, Property::eDouble, 2, true, "0" }, 565 { kOfxImageEffectPropProjectExtent, Property::eDouble, 2, true, "0" }, 566 { kOfxImageEffectPropProjectPixelAspectRatio, Property::eDouble, 1, true, "0" }, 567 { kOfxImageEffectInstancePropEffectDuration, Property::eDouble, 1, true, "0" }, 568 { kOfxImageEffectPropFrameRate , Property::eDouble, 1, true, "0" }, 569 { kOfxPropIsInteractive, Property::eInt, 1, true, "0" }, 570 # ifdef kOfxImageEffectPropInAnalysis 571 { kOfxImageEffectPropInAnalysis, Property::eInt, 1, false, "0" }, // removed in OFX 1.4 572 # endif 573 # ifdef OFX_EXTENSIONS_NUKE 574 //{ ".verbosityProp", Property::eInt, 2, true, "0" }, // Unknown Nuke property 575 # endif 576 # ifdef OFX_EXTENSIONS_VEGAS 577 { kOfxImageEffectPropVegasContext, Property::eString, 1, true, "" }, 578 # endif 579 # ifdef OFX_EXTENSIONS_NATRON 580 { kNatronOfxExtraCreatedPlanes, Property::eString, 0, true, ""}, 581 # endif 582 Property::propSpecEnd 583 }; 584 Instance(ImageEffectPlugin * plugin,Descriptor & other,const std::string & context,bool interactive)585 Instance::Instance(ImageEffectPlugin* plugin, 586 Descriptor &other, 587 const std::string &context, 588 bool interactive) 589 : Base(other) 590 , _plugin(plugin) 591 , _context(context) 592 , _descriptor(&other) 593 , _interactive(interactive) 594 , _created(false) 595 , _ownsData(true) 596 , _clipPrefsDirty(true) 597 , _continuousSamples(false) 598 , _frameVarying(false) 599 , _outputFrameRate(24) 600 { 601 int i = 0; 602 603 // this will add parameters that are needed in an instance but not a Descriptor 604 _properties.addProperties(effectInstanceStuff); 605 _properties.setChainedSet(&other.getProps()); 606 607 _properties.setPointerProperty(kOfxImageEffectPropPluginHandle, _plugin->getPluginHandle()->getOfxPlugin()); 608 609 _properties.setStringProperty(kOfxImageEffectPropContext,context); 610 _properties.setIntProperty(kOfxPropIsInteractive,interactive); 611 612 while(effectInstanceStuff[i].name) { 613 614 // don't set hooks for context or isinteractive or kOfxImageEffectInstancePropSequentialRender 615 // since we only set hook on the double properties anyway, don't do these comparisons since these properties 616 // are not of type Property::eDouble 617 618 //if(strcmp(effectInstanceStuff[i].name,kOfxImageEffectPropContext) && 619 // strcmp(effectInstanceStuff[i].name,kOfxPropIsInteractive) && 620 // strcmp(effectInstanceStuff[i].name,kOfxImageEffectInstancePropSequentialRender) ) 621 { 622 const Property::PropSpec& spec = effectInstanceStuff[i]; 623 switch (spec.type) { 624 case Property::eDouble: 625 _properties.setGetHook(spec.name, this); 626 break; 627 default: 628 break; 629 } 630 } 631 i++; 632 } 633 } 634 Instance(const Instance & other)635 Instance::Instance(const Instance& other) 636 : Base(other) 637 , Param::SetInstance(other) 638 , _plugin(other._plugin) 639 , _context(other._context) 640 , _descriptor(other._descriptor) 641 , _clips(other._clips) 642 , _interactive(other._interactive) 643 , _created(false) 644 , _ownsData(false) 645 , _clipPrefsDirty(other._clipPrefsDirty) 646 , _continuousSamples(other._continuousSamples) 647 , _frameVarying(other._frameVarying) 648 , _outputPreMultiplication(other._outputPreMultiplication) 649 , _outputFielding(other._outputFielding) 650 , _outputFrameRate(other._outputFrameRate) 651 { 652 653 } 654 655 /// implemented for Param::SetDescriptor getParamSetProps()656 Property::Set &Instance::getParamSetProps() 657 { 658 return _properties; 659 } 660 661 /// called after construction to populate clips and params populate()662 OfxStatus Instance::populate() 663 { 664 const std::vector<ClipDescriptor*>& clips = _descriptor->getClipsByOrder(); 665 666 int counter = 0; 667 for(std::vector<ClipDescriptor*>::const_iterator it=clips.begin(); 668 it!=clips.end(); 669 ++it, ++counter) { 670 const std::string &name = (*it)->getName(); 671 // foreach clip descriptor make a clip instance 672 ClipInstance* instance = newClipInstance(this, *it, counter); 673 if(!instance) return kOfxStatFailed; 674 675 _clips[name] = instance; 676 } 677 678 const std::list<Param::Descriptor*>& map = _descriptor->getParamList(); 679 680 std::map<std::string,std::vector<Param::Instance*> > parameters; 681 std::map<std::string, Param::Instance*> groups; 682 683 for(std::list<Param::Descriptor*>::const_iterator it=map.begin(); 684 it!=map.end(); 685 ++it) { 686 Param::Descriptor* descriptor = (*it); 687 // get the param descriptor 688 if(!descriptor) return kOfxStatErrValue; 689 690 // name of the parameter 691 std::string name = descriptor->getName(); 692 693 // get a param instance from a param descriptor 694 Param::Instance* instance = newParam(name,*descriptor); 695 if(!instance) return kOfxStatFailed; 696 697 // add the value into the param set instance 698 OfxStatus st = addParam(name,instance); 699 if(st != kOfxStatOK) return st; 700 701 std::string parent = instance->getParentName(); 702 703 if(parent!="") 704 parameters[parent].push_back(instance); 705 706 if(instance->getType()==kOfxParamTypeGroup){ 707 groups[instance->getName()]=instance; 708 } 709 } 710 711 // for each group parameter made 712 for(std::map<std::string, Param::Instance*>::iterator it=groups.begin(); 713 it!=groups.end(); 714 ++it) { 715 // cast to a group instance 716 Param::GroupInstance* group = dynamic_cast<Param::GroupInstance*>(it->second); 717 718 // if cast ok 719 if(group){ 720 // find the parameters whose parent was this group 721 std::map<std::string,std::vector<Param::Instance*> >::iterator it2 = parameters.find(group->getName()); 722 if(it2!=parameters.end()){ 723 // associate the group with its children, and the children with its parent group 724 group->setChildren(it2->second); 725 } 726 } 727 } 728 729 return kOfxStatOK; 730 } 731 732 // do nothing getDimension(const std::string & name) const733 int Instance::getDimension(const std::string &name) const OFX_EXCEPTION_SPEC { 734 printf("failing in %s with name=%s\n", __PRETTY_FUNCTION__, name.c_str()); 735 throw Property::Exception(kOfxStatErrMissingHostFeature); 736 } 737 upperGetDimension(const std::string & name)738 int Instance::upperGetDimension(const std::string &name) { 739 return _properties.getDimension(name); 740 } 741 notify(const std::string &,bool,int)742 void Instance::notify(const std::string &/*name*/, bool /*singleValue*/, int /*indexOrN*/) OFX_EXCEPTION_SPEC 743 { 744 printf("failing in %s\n", __PRETTY_FUNCTION__); 745 } 746 747 // don't know what to do reset(const std::string &)748 void Instance::reset(const std::string &/*name*/) OFX_EXCEPTION_SPEC { 749 printf("failing in %s\n", __PRETTY_FUNCTION__); 750 throw Property::Exception(kOfxStatErrMissingHostFeature); 751 } 752 753 // get the virutals for viewport size, pixel scale, background colour getDoubleProperty(const std::string & name,int index) const754 double Instance::getDoubleProperty(const std::string &name, int index) const OFX_EXCEPTION_SPEC 755 { 756 if(name==kOfxImageEffectPropProjectSize){ 757 if(index>=2) throw Property::Exception(kOfxStatErrBadIndex); 758 double values[2]; 759 getProjectSize(values[0],values[1]); 760 return values[index]; 761 } 762 else if(name==kOfxImageEffectPropProjectOffset){ 763 if(index>=2) throw Property::Exception(kOfxStatErrBadIndex); 764 double values[2]; 765 getProjectOffset(values[0],values[1]); 766 return values[index]; 767 } 768 else if(name==kOfxImageEffectPropProjectExtent){ 769 if(index>=2) throw Property::Exception(kOfxStatErrBadIndex); 770 double values[2]; 771 getProjectExtent(values[0],values[1]); 772 return values[index]; 773 } 774 else if(name==kOfxImageEffectPropProjectPixelAspectRatio){ 775 if(index>=1) throw Property::Exception(kOfxStatErrBadIndex); 776 return getProjectPixelAspectRatio(); 777 } 778 else if(name==kOfxImageEffectInstancePropEffectDuration){ 779 if(index>=1) throw Property::Exception(kOfxStatErrBadIndex); 780 return getEffectDuration(); 781 } 782 else if(name==kOfxImageEffectPropFrameRate){ 783 if(index>=1) throw Property::Exception(kOfxStatErrBadIndex); 784 return getFrameRate(); 785 } 786 else 787 throw Property::Exception(kOfxStatErrUnknown); 788 } 789 getDoublePropertyN(const std::string & name,double * first,int n) const790 void Instance::getDoublePropertyN(const std::string &name, double* first, int n) const OFX_EXCEPTION_SPEC 791 { 792 if(name==kOfxImageEffectPropProjectSize){ 793 if(n>2) throw Property::Exception(kOfxStatErrBadIndex); 794 getProjectSize(first[0],first[1]); 795 } 796 else if(name==kOfxImageEffectPropProjectOffset){ 797 if(n>2) throw Property::Exception(kOfxStatErrBadIndex); 798 getProjectOffset(first[0],first[1]); 799 } 800 else if(name==kOfxImageEffectPropProjectExtent){ 801 if(n>2) throw Property::Exception(kOfxStatErrBadIndex); 802 getProjectExtent(first[0],first[1]); 803 } 804 else if(name==kOfxImageEffectPropProjectPixelAspectRatio){ 805 if(n>1) throw Property::Exception(kOfxStatErrBadIndex); 806 *first = getProjectPixelAspectRatio(); 807 } 808 else if(name==kOfxImageEffectInstancePropEffectDuration){ 809 if(n>1) throw Property::Exception(kOfxStatErrBadIndex); 810 *first = getEffectDuration(); 811 } 812 else if(name==kOfxImageEffectPropFrameRate){ 813 if(n>1) throw Property::Exception(kOfxStatErrBadIndex); 814 *first = getFrameRate(); 815 } 816 else 817 throw Property::Exception(kOfxStatErrUnknown); 818 } 819 getStringProperty(const std::string & name,int n) const820 const std::string &Instance::getStringProperty(const std::string &name, int n) const OFX_EXCEPTION_SPEC 821 { 822 #ifdef OFX_EXTENSIONS_NUKE 823 if (name==kNatronOfxExtraCreatedPlanes) { 824 const std::vector<std::string>& userPlanes = getUserCreatedPlanes(); 825 if (n >= 0 && n < (int)userPlanes.size()) { 826 return userPlanes[n]; 827 } else { 828 throw Property::Exception(kOfxStatErrBadIndex); 829 } 830 } 831 #endif 832 throw Property::Exception(kOfxStatErrValue); 833 } 834 getStringPropertyN(const std::string & name,const char ** values,int count) const835 void Instance::getStringPropertyN(const std::string &name, const char** values, int count) const OFX_EXCEPTION_SPEC 836 { 837 if (count <= 0) throw Property::Exception(kOfxStatErrValue); 838 #ifdef OFX_EXTENSIONS_NATRON 839 if (name==kNatronOfxExtraCreatedPlanes) { 840 const std::vector<std::string>& componentsPresents = getUserCreatedPlanes(); 841 int minCount = (int)componentsPresents.size() < count ? (int)componentsPresents.size() : count; 842 for (int i = 0; i < minCount; ++i) { 843 values[i] = componentsPresents[i].c_str(); 844 } 845 return; 846 } 847 #endif 848 throw Property::Exception(kOfxStatErrValue); 849 } 850 851 #ifdef OFX_EXTENSIONS_NATRON getUserCreatedPlanes() const852 const std::vector<std::string>& Instance::getUserCreatedPlanes() const 853 { 854 static const std::vector<std::string> emptyVec; 855 return emptyVec; 856 } 857 858 #endif 859 ~Instance()860 Instance::~Instance(){ 861 // destroy the instance, only if succesfully created 862 if (_created) { 863 # ifdef OFX_DEBUG_ACTIONS 864 std::cout << "OFX WARNING: OFX::Host::ImageEffect::Instance::destroyInstanceAction() was not called before the OFX::Host::ImageEffect::Instance destructor."<<std::endl; 865 # endif 866 destroyInstanceAction(); 867 } 868 /// clobber my clips 869 if (_ownsData) { 870 std::map<std::string, ClipInstance*>::iterator i; 871 for(i = _clips.begin(); i != _clips.end(); ++i) { 872 if(i->second) 873 delete i->second; 874 i->second = NULL; 875 } 876 } 877 } 878 879 /// this is used to populate with any extra action in argumnents that may be needed setCustomInArgs(const std::string &,Property::Set &)880 void Instance::setCustomInArgs(const std::string &/*action*/, Property::Set &/*inArgs*/) 881 { 882 } 883 884 /// this is used to populate with any extra action out argumnents that may be needed setCustomOutArgs(const std::string &,Property::Set &)885 void Instance::setCustomOutArgs(const std::string &/*action*/, Property::Set &/*outArgs*/) 886 { 887 } 888 889 /// this is used to populate with any extra action out argumnents that may be needed examineOutArgs(const std::string &,OfxStatus,const Property::Set &)890 void Instance::examineOutArgs(const std::string &/*action*/, OfxStatus, const Property::Set &/*outArgs*/) 891 { 892 } 893 894 /// check for connection checkClipConnectionStatus() const895 bool Instance::checkClipConnectionStatus() const 896 { 897 std::map<std::string, ClipInstance*>::const_iterator i; 898 for(i = _clips.begin(); i != _clips.end(); ++i) { 899 if(!i->second->isOptional() && !i->second->getConnected()) { 900 return false; 901 } 902 } 903 return true; 904 } 905 906 // override this to make processing abort, return 1 to abort processing abort()907 int Instance::abort() { 908 return 0; 909 } 910 911 // override this to use your own memory instance - must inherrit from memory::instance newMemoryInstance(size_t)912 Memory::Instance* Instance::newMemoryInstance(size_t /*nBytes*/) { 913 return 0; 914 } 915 916 // return an memory::instance calls makeMemoryInstance that can be overriden imageMemoryAlloc(size_t nBytes)917 Memory::Instance* Instance::imageMemoryAlloc(size_t nBytes){ 918 Memory::Instance* instance = newMemoryInstance(nBytes); 919 if(instance) 920 return instance; 921 else{ 922 Memory::Instance* instance = new Memory::Instance; 923 instance->alloc(nBytes); 924 return instance; 925 } 926 } 927 928 // call the effect entry point mainEntry(const char * action,const void * handle,Property::Set * inArgs,Property::Set * outArgs)929 OfxStatus Instance::mainEntry(const char *action, 930 const void *handle, 931 Property::Set *inArgs, 932 Property::Set *outArgs) 933 { 934 if(_plugin){ 935 PluginHandle* pHandle = _plugin->getPluginHandle(); 936 if(pHandle){ 937 OfxPlugin* ofxPlugin = pHandle->getOfxPlugin(); 938 if(ofxPlugin){ 939 940 OfxPropertySetHandle inHandle = 0; 941 if(inArgs) { 942 setCustomInArgs(action, *inArgs); 943 inHandle = inArgs->getHandle(); 944 } 945 946 OfxPropertySetHandle outHandle = 0; 947 if(outArgs) { 948 setCustomOutArgs(action, *outArgs); 949 outHandle = outArgs->getHandle(); 950 } 951 952 OfxStatus stat; 953 try { 954 stat = ofxPlugin->mainEntry(action, handle, inHandle, outHandle); 955 } CatchAllSetStatus(stat, gImageEffectHost, ofxPlugin, action); 956 957 if(outArgs) 958 examineOutArgs(action, stat, *outArgs); 959 960 return stat; 961 } 962 return kOfxStatFailed; 963 } 964 return kOfxStatFailed; 965 } 966 return kOfxStatFailed; 967 } 968 969 // get the nth clip, in order of declaration getNthClip(int index)970 ClipInstance* Instance::getNthClip(int index) 971 { 972 const std::string name = _descriptor->getClipsByOrder()[index]->getName(); 973 return _clips[name]; 974 } 975 getClip(const std::string & name) const976 ClipInstance* Instance::getClip(const std::string& name) const { 977 std::map<std::string,ClipInstance*>::const_iterator it = _clips.find(name); 978 if(it!=_clips.end()){ 979 return it->second; 980 } 981 return 0; 982 } 983 984 // create an image effect instance createInstanceAction()985 OfxStatus Instance::createInstanceAction() 986 { 987 /// we need to init the clips before we call create instance incase 988 /// they try and fetch something in create instance, which they are allowed 989 setDefaultClipPreferences(); 990 991 # ifdef OFX_DEBUG_ACTIONS 992 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 993 const char* id = ofxp->pluginIdentifier; 994 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionCreateInstance<<"()"<<std::endl; 995 # endif 996 // now tell the plug-in to create instance 997 OfxStatus st = mainEntry(kOfxActionCreateInstance,this->getHandle(),0,0); 998 # ifdef OFX_DEBUG_ACTIONS 999 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionCreateInstance<<"()->"<<StatStr(st)<<std::endl; 1000 # endif 1001 1002 if (st == kOfxStatOK) { 1003 _created = true; 1004 } 1005 1006 return st; 1007 } 1008 1009 // destroy the instance, only if succesfully created destroyInstanceAction()1010 OfxStatus Instance::destroyInstanceAction() 1011 { 1012 OfxStatus st = kOfxStatFailed; 1013 if (_created) { 1014 # ifdef OFX_DEBUG_ACTIONS 1015 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1016 const char* id = ofxp->pluginIdentifier; 1017 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionDestroyInstance<<"()"<<std::endl; 1018 # endif 1019 OfxStatus st = mainEntry(kOfxActionDestroyInstance,this->getHandle(),0,0); 1020 # ifdef OFX_DEBUG_ACTIONS 1021 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionDestroyInstance<<"()->"<<StatStr(st)<<std::endl; 1022 # endif 1023 if (st == kOfxStatOK) { 1024 _created = false; 1025 } 1026 } 1027 1028 return st; 1029 } 1030 1031 // begin/change/end instance changed beginInstanceChangedAction(const std::string & why)1032 OfxStatus Instance::beginInstanceChangedAction(const std::string & why) 1033 { 1034 Property::PropSpec stuff[] = { 1035 { kOfxPropChangeReason, Property::eString, 1, true, why.c_str() }, 1036 Property::propSpecEnd 1037 }; 1038 1039 Property::Set inArgs(stuff); 1040 1041 # ifdef OFX_DEBUG_ACTIONS 1042 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceChanged<<"("<<why<<")"<<std::endl; 1043 # endif 1044 OfxStatus st = mainEntry(kOfxActionBeginInstanceChanged,this->getHandle(), &inArgs, 0); 1045 # ifdef OFX_DEBUG_ACTIONS 1046 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceChanged<<"("<<why<<")->"<<StatStr(st)<<std::endl; 1047 # endif 1048 return st; 1049 } 1050 paramInstanceChangedAction(const std::string & paramName,const std::string & why,OfxTime time,OfxPointD renderScale)1051 OfxStatus Instance::paramInstanceChangedAction(const std::string & paramName, 1052 const std::string & why, 1053 OfxTime time, 1054 OfxPointD renderScale) 1055 { 1056 Param::Instance* param = getParam(paramName); 1057 1058 if(isClipPreferencesSlaveParam(paramName)) 1059 _clipPrefsDirty = true; 1060 1061 if (!param) { 1062 return kOfxStatFailed; 1063 } 1064 if ( OFX::IsNaN(time) ) { 1065 return kOfxStatFailed; 1066 } 1067 1068 Property::PropSpec stuff[] = { 1069 { kOfxPropType, Property::eString, 1, true, kOfxTypeParameter }, 1070 { kOfxPropName, Property::eString, 1, true, paramName.c_str() }, 1071 { kOfxPropChangeReason, Property::eString, 1, true, why.c_str() }, 1072 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1073 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1074 # ifdef OFX_EXTENSIONS_NUKE 1075 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1076 # endif 1077 Property::propSpecEnd 1078 }; 1079 1080 Property::Set inArgs(stuff); 1081 1082 // add the second dimension of the render scale 1083 inArgs.setDoubleProperty(kOfxPropTime,time); 1084 1085 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1086 # ifdef OFX_DEBUG_ACTIONS 1087 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeParameter<<","<<paramName<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl; 1088 # endif 1089 1090 OfxStatus st = mainEntry(kOfxActionInstanceChanged,this->getHandle(), &inArgs, 0); 1091 # ifdef OFX_DEBUG_ACTIONS 1092 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeParameter<<","<<paramName<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st)<<std::endl; 1093 # endif 1094 return st; 1095 } 1096 clipInstanceChangedAction(const std::string & clipName,const std::string & why,OfxTime time,OfxPointD renderScale)1097 OfxStatus Instance::clipInstanceChangedAction(const std::string & clipName, 1098 const std::string & why, 1099 OfxTime time, 1100 OfxPointD renderScale) 1101 { 1102 if ( OFX::IsNaN(time) ) { 1103 return kOfxStatFailed; 1104 } 1105 _clipPrefsDirty = true; 1106 std::map<std::string,ClipInstance*>::iterator it=_clips.find(clipName); 1107 if(it!=_clips.end()) 1108 return (it->second)->instanceChangedAction(why,time,renderScale); 1109 else 1110 return kOfxStatFailed; 1111 } 1112 endInstanceChangedAction(const std::string & why)1113 OfxStatus Instance::endInstanceChangedAction(const std::string & why) 1114 { 1115 Property::PropSpec whyStuff[] = { 1116 { kOfxPropChangeReason, Property::eString, 1, true, why.c_str() }, 1117 Property::propSpecEnd 1118 }; 1119 1120 Property::Set inArgs(whyStuff); 1121 # ifdef OFX_DEBUG_ACTIONS 1122 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceChanged<<"("<<why<<")"<<std::endl; 1123 # endif 1124 1125 OfxStatus st = mainEntry(kOfxActionEndInstanceChanged,this->getHandle(), &inArgs, 0); 1126 # ifdef OFX_DEBUG_ACTIONS 1127 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceChanged<<"("<<why<<")->"<<StatStr(st)<<std::endl; 1128 # endif 1129 return st; 1130 } 1131 1132 // purge your caches purgeCachesAction()1133 OfxStatus Instance::purgeCachesAction(){ 1134 # ifdef OFX_DEBUG_ACTIONS 1135 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionPurgeCaches<<"()"<<std::endl; 1136 # endif 1137 OfxStatus st = mainEntry(kOfxActionPurgeCaches ,this->getHandle(),0,0); 1138 # ifdef OFX_DEBUG_ACTIONS 1139 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionPurgeCaches<<"()->"<<StatStr(st)<<std::endl; 1140 # endif 1141 return st; 1142 } 1143 1144 // sync your private data syncPrivateDataAction()1145 OfxStatus Instance::syncPrivateDataAction(){ 1146 # ifdef OFX_DEBUG_ACTIONS 1147 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionSyncPrivateData<<"()"<<std::endl; 1148 # endif 1149 // Only call kOfxActionSyncPrivateData if kOfxPropParamSetNeedsSyncing is not set, 1150 // or if it is set to 1. 1151 // see http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#kOfxPropParamSetNeedsSyncing 1152 Property::Int* s = _properties.fetchIntProperty(kOfxPropParamSetNeedsSyncing); 1153 bool needsSyncing = s ? s->getValue() : true; 1154 OfxStatus st = kOfxStatReplyDefault; 1155 if (needsSyncing) { 1156 st = mainEntry(kOfxActionSyncPrivateData,this->getHandle(),0,0); 1157 if (s) { 1158 s->setValue(0); 1159 } 1160 } 1161 # ifdef OFX_DEBUG_ACTIONS 1162 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionSyncPrivateData<<"()->"<<StatStr(st)<<std::endl; 1163 # endif 1164 return st; 1165 } 1166 1167 // begin/end edit instance beginInstanceEditAction()1168 OfxStatus Instance::beginInstanceEditAction(){ 1169 # ifdef OFX_DEBUG_ACTIONS 1170 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceEdit<<"()"<<std::endl; 1171 # endif 1172 OfxStatus st = mainEntry(kOfxActionBeginInstanceEdit,this->getHandle(),0,0); 1173 # ifdef OFX_DEBUG_ACTIONS 1174 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceEdit<<"()->"<<StatStr(st)<<std::endl; 1175 # endif 1176 return st; 1177 } 1178 endInstanceEditAction()1179 OfxStatus Instance::endInstanceEditAction(){ 1180 # ifdef OFX_DEBUG_ACTIONS 1181 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceEdit<<"()"<<std::endl; 1182 # endif 1183 OfxStatus st = mainEntry(kOfxActionEndInstanceEdit,this->getHandle(),0,0); 1184 # ifdef OFX_DEBUG_ACTIONS 1185 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceEdit<<"()->"<<StatStr(st)<<std::endl; 1186 # endif 1187 return st; 1188 } 1189 1190 # ifdef OFX_SUPPORTS_OPENGLRENDER 1191 // attach/detach OpenGL context contextAttachedAction(void * & contextData)1192 OfxStatus Instance::contextAttachedAction( 1193 # ifdef OFX_EXTENSIONS_NATRON 1194 void* &contextData 1195 # endif 1196 ) 1197 { 1198 static const Property::PropSpec outStuff[] = { 1199 #ifdef OFX_EXTENSIONS_NATRON 1200 { kNatronOfxImageEffectPropOpenGLContextData , Property::ePointer, 1, false, NULL }, 1201 #endif 1202 Property::propSpecEnd 1203 }; 1204 1205 Property::Set outArgs(outStuff); 1206 1207 # ifdef OFX_DEBUG_ACTIONS 1208 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextAttached<<"()"<<std::endl; 1209 # endif 1210 OfxStatus st = mainEntry(kOfxActionOpenGLContextAttached,this->getHandle(), 0, &outArgs); 1211 if(st == kOfxStatOK || st == kOfxStatReplyDefault) { 1212 # ifdef OFX_EXTENSIONS_NATRON 1213 contextData = outArgs.getPointerProperty(kNatronOfxImageEffectPropOpenGLContextData); 1214 # endif 1215 } 1216 # ifdef OFX_DEBUG_ACTIONS 1217 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextAttached<<"()->"<<StatStr(st); 1218 # ifdef OFX_EXTENSIONS_NATRON 1219 if(st == kOfxStatOK) { 1220 std::cout << ": (" << contextData << ")"; 1221 } 1222 # endif 1223 std::cout << std::endl; 1224 # endif 1225 return st; 1226 } 1227 contextDetachedAction(void * contextData)1228 OfxStatus Instance::contextDetachedAction( 1229 # ifdef OFX_EXTENSIONS_NATRON 1230 void* contextData 1231 # endif 1232 ) 1233 { 1234 static const Property::PropSpec inStuff[] = { 1235 #ifdef OFX_EXTENSIONS_NATRON 1236 { kNatronOfxImageEffectPropOpenGLContextData , Property::ePointer, 1, false, NULL }, 1237 #endif 1238 Property::propSpecEnd 1239 }; 1240 1241 Property::Set inArgs(inStuff); 1242 1243 #ifdef OFX_EXTENSIONS_NATRON 1244 inArgs.setPointerProperty(kNatronOfxImageEffectPropOpenGLContextData, contextData); 1245 #endif 1246 1247 # ifdef OFX_DEBUG_ACTIONS 1248 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextDetached<<"("; 1249 # ifdef OFX_EXTENSIONS_NATRON 1250 std:: cout << contextData; 1251 # endif 1252 std::cout << ")" <<std::endl; 1253 # endif 1254 OfxStatus st = mainEntry(kOfxActionOpenGLContextDetached,this->getHandle(),&inArgs,0); 1255 # ifdef OFX_DEBUG_ACTIONS 1256 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextDetached<<"()->"<<StatStr(st)<<std::endl; 1257 # endif 1258 return st; 1259 } 1260 # endif 1261 beginRenderAction(OfxTime startFrame,OfxTime endFrame,OfxTime step,bool interactive,OfxPointD renderScale,bool sequentialRender,bool interactiveRender,bool openGLRender,void * contextData,bool draftRender,int view)1262 OfxStatus Instance::beginRenderAction(OfxTime startFrame, 1263 OfxTime endFrame, 1264 OfxTime step, 1265 bool interactive, 1266 OfxPointD renderScale, 1267 bool sequentialRender, 1268 bool interactiveRender, 1269 # ifdef OFX_SUPPORTS_OPENGLRENDER 1270 bool openGLRender, 1271 # ifdef OFX_EXTENSIONS_NATRON 1272 void* contextData, 1273 # endif 1274 # endif 1275 bool draftRender 1276 # ifdef OFX_EXTENSIONS_NUKE 1277 , 1278 int view 1279 # endif 1280 ) 1281 { 1282 if ( OFX::IsNaN(startFrame) || 1283 OFX::IsNaN(endFrame) || 1284 OFX::IsNaN(step) ) { 1285 return kOfxStatFailed; 1286 } 1287 Property::PropSpec stuff[] = { 1288 { kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" }, 1289 { kOfxImageEffectPropFrameStep, Property::eDouble, 1, true, "0" }, 1290 { kOfxPropIsInteractive, Property::eInt, 1, true, "0" }, 1291 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1292 { kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" }, 1293 { kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" }, 1294 # ifdef OFX_SUPPORTS_OPENGLRENDER 1295 { kOfxImageEffectPropOpenGLEnabled, Property::eInt, 1, true, "0" }, // OFX 1.3 1296 # ifdef OFX_EXTENSIONS_NATRON 1297 { kNatronOfxImageEffectPropOpenGLContextData , Property::ePointer, 1, false, NULL }, 1298 # endif 1299 # endif 1300 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 1301 # ifdef OFX_EXTENSIONS_RESOLVE 1302 { kOfxImageEffectPropOpenCLEnabled, Property::eInt, 1, true, "0" }, 1303 { kOfxImageEffectPropCudaEnabled, Property::eInt, 1, true, "0" }, 1304 { kOfxImageEffectPropOpenCLCommandQueue, Property::ePointer, 1, false, "0" }, 1305 # endif 1306 # ifdef OFX_EXTENSIONS_NUKE 1307 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1308 # endif 1309 Property::propSpecEnd 1310 }; 1311 1312 Property::Set inArgs(stuff); 1313 1314 // set up second dimension for frame range and render scale 1315 inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,startFrame, 0); 1316 inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,endFrame, 1); 1317 1318 inArgs.setDoubleProperty(kOfxImageEffectPropFrameStep,step); 1319 1320 inArgs.setIntProperty(kOfxPropIsInteractive,interactive); 1321 1322 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1323 1324 inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender); 1325 inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender); 1326 # ifdef OFX_SUPPORTS_OPENGLRENDER 1327 inArgs.setIntProperty(kOfxImageEffectPropOpenGLEnabled,openGLRender); 1328 # ifdef OFX_EXTENSIONS_NATRON 1329 inArgs.setPointerProperty(kNatronOfxImageEffectPropOpenGLContextData, contextData); 1330 # endif 1331 # endif 1332 inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender); 1333 1334 # ifdef OFX_EXTENSIONS_NUKE 1335 inArgs.setIntProperty(kFnOfxImageEffectPropView,view); 1336 # endif 1337 1338 # ifdef OFX_DEBUG_ACTIONS 1339 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionBeginSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1340 # ifdef OFX_EXTENSIONS_NUKE 1341 <<","<<view 1342 # endif 1343 <<")"<<std::endl; 1344 # endif 1345 1346 OfxStatus st = mainEntry(kOfxImageEffectActionBeginSequenceRender, this->getHandle(), &inArgs, 0); 1347 # ifdef OFX_DEBUG_ACTIONS 1348 std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionBeginSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1349 # ifdef OFX_EXTENSIONS_NUKE 1350 <<","<<view 1351 # endif 1352 <<")->"<<StatStr(st)<<std::endl; 1353 # endif 1354 return st; 1355 } 1356 renderAction(OfxTime time,const std::string & field,const OfxRectI & renderRoI,OfxPointD renderScale,bool sequentialRender,bool interactiveRender,bool openGLRender,void * contextData,bool draftRender,int view,int nViews,const std::list<std::string> & planes)1357 OfxStatus Instance::renderAction(OfxTime time, 1358 const std::string & field, 1359 const OfxRectI &renderRoI, 1360 OfxPointD renderScale, 1361 bool sequentialRender, 1362 bool interactiveRender, 1363 # ifdef OFX_SUPPORTS_OPENGLRENDER 1364 bool openGLRender, 1365 # ifdef OFX_EXTENSIONS_NATRON 1366 void* contextData, 1367 # endif 1368 # endif 1369 bool draftRender 1370 #if defined(OFX_EXTENSIONS_VEGAS) || defined(OFX_EXTENSIONS_NUKE) 1371 , 1372 int view 1373 #endif 1374 #ifdef OFX_EXTENSIONS_VEGAS 1375 , 1376 int nViews 1377 #endif 1378 #ifdef OFX_EXTENSIONS_NUKE 1379 , 1380 const std::list<std::string>& planes 1381 #endif 1382 ) 1383 { 1384 if ( OFX::IsNaN(time) ) { 1385 return kOfxStatFailed; 1386 } 1387 static const Property::PropSpec inStuff[] = { 1388 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1389 { kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" }, 1390 { kOfxImageEffectPropRenderWindow, Property::eInt, 4, true, "0" }, 1391 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1392 { kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" }, 1393 { kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" }, 1394 # ifdef OFX_SUPPORTS_OPENGLRENDER 1395 { kOfxImageEffectPropOpenGLEnabled, Property::eInt, 1, true, "0" }, // OFX 1.3 1396 # ifdef OFX_EXTENSIONS_NATRON 1397 { kNatronOfxImageEffectPropOpenGLContextData , Property::ePointer, 1, false, "0" }, 1398 # endif 1399 # endif 1400 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 1401 # ifdef OFX_EXTENSIONS_RESOLVE 1402 { kOfxImageEffectPropOpenCLEnabled, Property::eInt, 1, true, "0" }, 1403 { kOfxImageEffectPropCudaEnabled, Property::eInt, 1, true, "0" }, 1404 { kOfxImageEffectPropOpenCLCommandQueue, Property::ePointer, 1, false, "0" }, 1405 # endif 1406 # ifdef OFX_EXTENSIONS_VEGAS 1407 { kOfxImageEffectPropRenderView, Property::eInt, 1, true, "0" }, 1408 { kOfxImageEffectPropViewsToRender, Property::eInt, 1, true, "1" }, 1409 { kOfxImageEffectPropRenderQuality, Property::eString, 1, true, "" }, 1410 # endif 1411 # ifdef OFX_EXTENSIONS_NUKE 1412 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1413 { kOfxImageEffectPropRenderPlanes, Property::eString, 0, true, "" }, 1414 # endif 1415 Property::propSpecEnd 1416 }; 1417 1418 Property::Set inArgs(inStuff); 1419 1420 inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field); 1421 inArgs.setDoubleProperty(kOfxPropTime,time); 1422 inArgs.setIntPropertyN(kOfxImageEffectPropRenderWindow, &renderRoI.x1, 4); 1423 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1424 inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender); 1425 inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender); 1426 # ifdef OFX_SUPPORTS_OPENGLRENDER 1427 inArgs.setIntProperty(kOfxImageEffectPropOpenGLEnabled,openGLRender); 1428 # ifdef OFX_EXTENSIONS_NATRON 1429 inArgs.setPointerProperty(kNatronOfxImageEffectPropOpenGLContextData, contextData); 1430 # endif 1431 # endif 1432 inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender); 1433 # ifdef OFX_EXTENSIONS_VEGAS 1434 inArgs.setIntProperty(kOfxImageEffectPropRenderView,view); 1435 inArgs.setIntProperty(kOfxImageEffectPropViewsToRender,nViews); 1436 # endif 1437 # ifdef OFX_EXTENSIONS_NUKE 1438 inArgs.setIntProperty(kFnOfxImageEffectPropView,view); 1439 int k = 0; 1440 for (std::list<std::string>::const_iterator it = planes.begin(); it != planes.end(); ++it,++k) { 1441 inArgs.setStringProperty(kOfxImageEffectPropRenderPlanes,*it,k); 1442 } 1443 # endif 1444 # if defined(OFX_EXTENSIONS_VEGAS) || defined(OFX_EXTENSIONS_NUKE) 1445 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 1446 it!=_clips.end(); 1447 ++it) { 1448 it->second->setView(view); 1449 } 1450 # endif 1451 1452 # ifdef OFX_DEBUG_ACTIONS 1453 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1454 const char* id = ofxp->pluginIdentifier; 1455 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionRender<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1456 # if defined(OFX_EXTENSIONS_VEGAS) || defined(OFX_EXTENSIONS_NUKE) 1457 <<","<<view 1458 # endif 1459 # ifdef OFX_EXTENSIONS_VEGAS 1460 <<","<<nViews 1461 # endif 1462 <<")"<<std::endl; 1463 # endif 1464 1465 OfxStatus st = mainEntry(kOfxImageEffectActionRender,this->getHandle(), &inArgs, 0); 1466 # ifdef OFX_DEBUG_ACTIONS 1467 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionRender<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1468 # if defined(OFX_EXTENSIONS_VEGAS) || defined(OFX_EXTENSIONS_NUKE) 1469 <<","<<view 1470 # endif 1471 # ifdef OFX_EXTENSIONS_VEGAS 1472 <<","<<nViews 1473 # endif 1474 <<")->"<<StatStr(st)<<std::endl; 1475 # endif 1476 return st; 1477 } 1478 endRenderAction(OfxTime startFrame,OfxTime endFrame,OfxTime step,bool interactive,OfxPointD renderScale,bool sequentialRender,bool interactiveRender,bool openGLRender,void * contextData,bool draftRender,int view)1479 OfxStatus Instance::endRenderAction(OfxTime startFrame, 1480 OfxTime endFrame, 1481 OfxTime step, 1482 bool interactive, 1483 OfxPointD renderScale, 1484 bool sequentialRender, 1485 bool interactiveRender, 1486 # ifdef OFX_SUPPORTS_OPENGLRENDER 1487 bool openGLRender, 1488 # ifdef OFX_EXTENSIONS_NATRON 1489 void* contextData, 1490 # endif 1491 # endif 1492 bool draftRender 1493 # ifdef OFX_EXTENSIONS_NUKE 1494 , 1495 int view 1496 # endif 1497 ) 1498 { 1499 if ( OFX::IsNaN(startFrame) || 1500 OFX::IsNaN(endFrame) || 1501 OFX::IsNaN(step) ) { 1502 return kOfxStatFailed; 1503 } 1504 static const Property::PropSpec inStuff[] = { 1505 { kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" }, 1506 { kOfxImageEffectPropFrameStep, Property::eDouble, 1, true, "0" }, 1507 { kOfxPropIsInteractive, Property::eInt, 1, true, "0" }, 1508 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1509 { kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" }, 1510 { kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" }, 1511 # ifdef OFX_SUPPORTS_OPENGLRENDER 1512 { kOfxImageEffectPropOpenGLEnabled, Property::eInt, 1, true, "0" }, // OFX 1.3 1513 # ifdef OFX_EXTENSIONS_NATRON 1514 { kNatronOfxImageEffectPropOpenGLContextData , Property::ePointer, 1, false, "0" }, 1515 # endif 1516 # endif 1517 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 1518 # ifdef OFX_EXTENSIONS_RESOLVE 1519 { kOfxImageEffectPropOpenCLEnabled, Property::eInt, 1, true, "0" }, 1520 { kOfxImageEffectPropCudaEnabled, Property::eInt, 1, true, "0" }, 1521 { kOfxImageEffectPropOpenCLCommandQueue, Property::ePointer, 1, false, "0" }, 1522 # endif 1523 # ifdef OFX_EXTENSIONS_NUKE 1524 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1525 # endif 1526 Property::propSpecEnd 1527 }; 1528 1529 Property::Set inArgs(inStuff); 1530 1531 inArgs.setDoubleProperty(kOfxImageEffectPropFrameStep,step); 1532 1533 inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,startFrame, 0); 1534 inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,endFrame, 1); 1535 inArgs.setIntProperty(kOfxPropIsInteractive,interactive); 1536 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1537 inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender); 1538 inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender); 1539 # ifdef OFX_SUPPORTS_OPENGLRENDER 1540 inArgs.setIntProperty(kOfxImageEffectPropOpenGLEnabled,openGLRender); 1541 # ifdef OFX_EXTENSIONS_NATRON 1542 inArgs.setPointerProperty(kNatronOfxImageEffectPropOpenGLContextData, contextData); 1543 # endif 1544 # endif 1545 inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender); 1546 # ifdef OFX_EXTENSIONS_NUKE 1547 inArgs.setIntProperty(kFnOfxImageEffectPropView,view); 1548 # endif 1549 # ifdef OFX_DEBUG_ACTIONS 1550 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1551 const char* id = ofxp->pluginIdentifier; 1552 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionEndSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1553 # ifdef OFX_EXTENSIONS_NUKE 1554 <<","<<view 1555 # endif 1556 <<")"<<std::endl; 1557 # endif 1558 1559 OfxStatus st = mainEntry(kOfxImageEffectActionEndSequenceRender,this->getHandle(), &inArgs, 0); 1560 # ifdef OFX_DEBUG_ACTIONS 1561 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionEndSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender<<","<<draftRender 1562 # ifdef OFX_EXTENSIONS_NUKE 1563 <<","<<view 1564 # endif 1565 <<")->"<<StatStr(st)<<std::endl; 1566 # endif 1567 return st; 1568 } 1569 1570 #ifdef OFX_EXTENSIONS_NUKE getTransformAction(OfxTime time,const std::string & field,OfxPointD renderScale,bool draftRender,int view,std::string & clip,double transform[9])1571 OfxStatus Instance::getTransformAction(OfxTime time, 1572 const std::string& field, 1573 OfxPointD renderScale, 1574 bool draftRender, 1575 int view, 1576 std::string& clip, 1577 double transform[9]) 1578 { 1579 if ( OFX::IsNaN(time) ) { 1580 return kOfxStatFailed; 1581 } 1582 static const Property::PropSpec inStuff[] = { 1583 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1584 { kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" }, 1585 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1586 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 1587 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1588 Property::propSpecEnd 1589 }; 1590 1591 static const Property::PropSpec outStuff[] = { 1592 { kOfxPropName, Property::eString, 1, false, "" }, 1593 { kFnOfxPropMatrix2D, Property::eDouble, 9, false, "0.0" }, 1594 Property::propSpecEnd 1595 }; 1596 1597 Property::Set inArgs(inStuff); 1598 Property::Set outArgs(outStuff); 1599 1600 inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field); 1601 inArgs.setDoubleProperty(kOfxPropTime,time); 1602 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1603 inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender); 1604 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 1605 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 1606 it!=_clips.end(); 1607 ++it) { 1608 it->second->setView(view); 1609 } 1610 1611 # ifdef OFX_DEBUG_ACTIONS 1612 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1613 const char* id = ofxp->pluginIdentifier; 1614 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetTransform<<"("<<time<<","<<field<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<view<<")"<<std::endl; 1615 # endif 1616 1617 OfxStatus st = mainEntry(kFnOfxImageEffectActionGetTransform,this->getHandle(), &inArgs, &outArgs); 1618 # ifdef OFX_DEBUG_ACTIONS 1619 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetTransform<<"("<<time<<","<<field<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<view<<")->"<<StatStr(st)<<std::endl; 1620 # endif 1621 1622 if(st == kOfxStatOK) { 1623 clip = outArgs.getStringProperty(kOfxPropName); 1624 outArgs.getDoublePropertyN(kFnOfxPropMatrix2D, transform, 9); 1625 } 1626 1627 return st; 1628 } 1629 #endif // OFX_EXTENSIONS_NUKE 1630 1631 #ifdef OFX_EXTENSIONS_NATRON getInverseDistortionAction(OfxTime time,const std::string & field,OfxPointD renderScale,bool draftRender,int view,std::string & clip,double transform[9],OfxInverseDistortionFunctionV1 * distortionFunc,void ** distortionFunctionData,int * distortionFunctionDataSize,OfxInverseDistortionDataFreeFunctionV1 * freeDataFunction)1632 OfxStatus Instance::getInverseDistortionAction(OfxTime time, 1633 const std::string& field, 1634 OfxPointD renderScale, 1635 bool draftRender, 1636 int view, 1637 std::string& clip, 1638 double transform[9], 1639 OfxInverseDistortionFunctionV1* distortionFunc, 1640 void** distortionFunctionData, 1641 int* distortionFunctionDataSize, 1642 OfxInverseDistortionDataFreeFunctionV1* freeDataFunction) 1643 { 1644 if ( OFX::IsNaN(time) ) { 1645 return kOfxStatFailed; 1646 } 1647 static const Property::PropSpec inStuff[] = { 1648 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1649 { kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" }, 1650 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1651 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 1652 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1653 Property::propSpecEnd 1654 }; 1655 1656 static const Property::PropSpec outStuff[] = { 1657 { kOfxPropName, Property::eString, 1, false, "" }, 1658 { kOfxPropMatrix3x3, Property::eDouble, 9, false, "0.0" }, 1659 { kOfxPropInverseDistortionFunction, Property::ePointer, 1, false, NULL }, 1660 { kOfxPropInverseDistortionFunctionData, Property::ePointer, 1, false, NULL }, 1661 { kOfxPropInverseDistortionFunctionDataSize, Property::eInt, 1, false, "0" }, 1662 { kOfxPropInverseDistortionDataFreeFunction, Property::ePointer, 1, false, NULL }, 1663 Property::propSpecEnd 1664 }; 1665 1666 Property::Set inArgs(inStuff); 1667 Property::Set outArgs(outStuff); 1668 1669 inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field); 1670 inArgs.setDoubleProperty(kOfxPropTime,time); 1671 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1672 inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender); 1673 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 1674 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 1675 it!=_clips.end(); 1676 ++it) { 1677 it->second->setView(view); 1678 } 1679 1680 # ifdef OFX_DEBUG_ACTIONS 1681 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1682 const char* id = ofxp->pluginIdentifier; 1683 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetInverseDistortion<<"("<<time<<","<<field<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<view<<")"<<std::endl; 1684 # endif 1685 1686 OfxStatus st = mainEntry(kOfxImageEffectActionGetInverseDistortion,this->getHandle(), &inArgs, &outArgs); 1687 # ifdef OFX_DEBUG_ACTIONS 1688 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetInverseDistortion<<"("<<time<<","<<field<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<view<<")->"<<StatStr(st)<<std::endl; 1689 # endif 1690 1691 if (st == kOfxStatOK) { 1692 clip = outArgs.getStringProperty(kOfxPropName); 1693 outArgs.getDoublePropertyN(kOfxPropMatrix3x3, transform, 9); 1694 *distortionFunc = (OfxInverseDistortionFunctionV1)outArgs.getPointerProperty(kOfxPropInverseDistortionFunction); 1695 *distortionFunctionData = outArgs.getPointerProperty(kOfxPropInverseDistortionFunctionData); 1696 *distortionFunctionDataSize = outArgs.getIntProperty(kOfxPropInverseDistortionFunctionDataSize); 1697 *freeDataFunction = (OfxInverseDistortionDataFreeFunctionV1)outArgs.getPointerProperty(kOfxPropInverseDistortionDataFreeFunction); 1698 } 1699 1700 return st; 1701 } 1702 #endif // OFX_EXTENSIONS_NATRON 1703 1704 /// calculate the default rod for this effect instance calcDefaultRegionOfDefinition(OfxTime time,OfxPointD,int view) const1705 OfxRectD Instance::calcDefaultRegionOfDefinition(OfxTime time, 1706 OfxPointD /*renderScale*/ 1707 # ifdef OFX_EXTENSIONS_NUKE 1708 , 1709 int view 1710 # endif 1711 ) const 1712 { 1713 OfxRectD rod; 1714 if ( OFX::IsNaN(time) ) { 1715 rod.x1 = rod. x2 = rod.y1 = rod.y2 = 0.; 1716 return rod; 1717 } 1718 1719 // figure out the default contexts 1720 if( 1721 #ifdef OFX_EXTENSIONS_TUTTLE 1722 _context == kOfxImageEffectContextReader || 1723 #endif 1724 _context == kOfxImageEffectContextGenerator) { 1725 // generator is the extent 1726 rod.x1 = rod.y1 = 0; 1727 getProjectExtent(rod.x2, rod.y2); 1728 } 1729 else if(_context == kOfxImageEffectContextFilter || 1730 #ifdef OFX_EXTENSIONS_TUTTLE 1731 _context == kOfxImageEffectContextWriter || 1732 #endif 1733 _context == kOfxImageEffectContextPaint) { 1734 // filter and paint default to the input clip 1735 ClipInstance *clip = getClip(kOfxImageEffectSimpleSourceClipName); 1736 if(clip) { 1737 # ifdef OFX_EXTENSIONS_NUKE 1738 rod = clip->getRegionOfDefinition(time, view); 1739 # else 1740 rod = clip->getRegionOfDefinition(time); 1741 # endif 1742 } else { 1743 throw Property::Exception(kOfxStatFailed); 1744 } 1745 } 1746 else if(_context == kOfxImageEffectContextTransition) { 1747 // transition is the union of the two clips 1748 ClipInstance *clipFrom = getClip(kOfxImageEffectTransitionSourceFromClipName); 1749 ClipInstance *clipTo = getClip(kOfxImageEffectTransitionSourceToClipName); 1750 if(clipFrom && clipTo) { 1751 # ifdef OFX_EXTENSIONS_NUKE 1752 rod = clipFrom->getRegionOfDefinition(time, view); 1753 rod = Union(rod, clipTo->getRegionOfDefinition(time, view)); 1754 # else 1755 rod = clipFrom->getRegionOfDefinition(time); 1756 rod = Union(rod, clipTo->getRegionOfDefinition(time)); 1757 # endif 1758 } else { 1759 throw Property::Exception(kOfxStatFailed); 1760 } 1761 } 1762 else if(_context == kOfxImageEffectContextGeneral 1763 #ifdef OFX_EXTENSIONS_NATRON 1764 || _context == kNatronOfxImageEffectContextTracker 1765 #endif 1766 ) { 1767 // general context is the union of all the non optional clips 1768 bool gotOne = false; 1769 for(std::map<std::string, ClipInstance*>::const_iterator it=_clips.begin(); 1770 it!=_clips.end(); 1771 ++it) { 1772 ClipInstance *clip = it->second; 1773 if(!clip->isOutput() && (!clip->isOptional() || (clip->getConnected() && clip->getName() == kOfxImageEffectSimpleSourceClipName))) { 1774 # ifdef OFX_EXTENSIONS_NUKE 1775 if(!gotOne) 1776 rod = clip->getRegionOfDefinition(time, view); 1777 else 1778 rod = Union(rod, clip->getRegionOfDefinition(time, view)); 1779 # else 1780 if(!gotOne) 1781 rod = clip->getRegionOfDefinition(time); 1782 else 1783 rod = Union(rod, clip->getRegionOfDefinition(time)); 1784 # endif 1785 gotOne = true; 1786 } 1787 } 1788 1789 if(!gotOne) { 1790 /// no non optionals? then be the extent 1791 rod.x1 = rod.y1 = 0; 1792 getProjectExtent(rod.x2, rod.y2); 1793 } 1794 1795 } 1796 else if(_context == kOfxImageEffectContextRetimer) { 1797 // retimer 1798 ClipInstance *clip = getClip(kOfxImageEffectSimpleSourceClipName); 1799 if(clip) { 1800 Param::DoubleInstance *param = dynamic_cast<Param::DoubleInstance *>(getParam(kOfxImageEffectRetimerParamName)); 1801 if(param) { 1802 double srctime; 1803 OfxStatus stat = param->get(time, srctime); 1804 if (stat != kOfxStatOK) { 1805 throw Property::Exception(stat); 1806 } 1807 # ifdef OFX_EXTENSIONS_NUKE 1808 rod = clip->getRegionOfDefinition(floor(srctime), view); 1809 rod = Union(rod, clip->getRegionOfDefinition(ceil(srctime), view)); 1810 # else 1811 rod = clip->getRegionOfDefinition(floor(srctime)); 1812 rod = Union(rod, clip->getRegionOfDefinition(ceil(srctime))); 1813 # endif 1814 } else { 1815 throw Property::Exception(kOfxStatFailed); 1816 } 1817 } else { 1818 throw Property::Exception(kOfxStatFailed); 1819 } 1820 } 1821 else { 1822 // unknown context 1823 throw Property::Exception(kOfxStatErrMissingHostFeature); 1824 } 1825 1826 return rod; 1827 } 1828 1829 //////////////////////////////////////////////////////////////////////////////// 1830 // RoD call getRegionOfDefinitionAction(OfxTime time,OfxPointD renderScale,int view,OfxRectD & rod)1831 OfxStatus Instance::getRegionOfDefinitionAction(OfxTime time, 1832 OfxPointD renderScale, 1833 #ifdef OFX_EXTENSIONS_NUKE 1834 int view, 1835 #endif 1836 OfxRectD &rod) 1837 { 1838 if ( OFX::IsNaN(time) ) { 1839 return kOfxStatFailed; 1840 } 1841 static const Property::PropSpec inStuff[] = { 1842 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1843 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1844 #ifdef OFX_EXTENSIONS_NUKE 1845 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1846 #endif 1847 Property::propSpecEnd 1848 }; 1849 1850 static const Property::PropSpec outStuff[] = { 1851 { kOfxImageEffectPropRegionOfDefinition , Property::eDouble, 4, false, "0" }, 1852 Property::propSpecEnd 1853 }; 1854 1855 Property::Set inArgs(inStuff); 1856 Property::Set outArgs(outStuff); 1857 1858 inArgs.setDoubleProperty(kOfxPropTime,time); 1859 #ifdef OFX_EXTENSIONS_NUKE 1860 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 1861 #endif 1862 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1863 1864 # ifdef OFX_DEBUG_ACTIONS 1865 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1866 const char* id = ofxp->pluginIdentifier; 1867 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetRegionOfDefinition<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl; 1868 # endif 1869 OfxStatus stat = mainEntry(kOfxImageEffectActionGetRegionOfDefinition, 1870 this->getHandle(), 1871 &inArgs, 1872 &outArgs); 1873 if(stat == kOfxStatOK) { 1874 outArgs.getDoublePropertyN(kOfxImageEffectPropRegionOfDefinition, &rod.x1, 4); 1875 } 1876 else if(stat == kOfxStatReplyDefault) { 1877 rod = calcDefaultRegionOfDefinition(time, renderScale 1878 # ifdef OFX_EXTENSIONS_NUKE 1879 , 1880 view 1881 # endif 1882 ); 1883 } 1884 1885 1886 # ifdef OFX_DEBUG_ACTIONS 1887 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetRegionOfDefinition<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(stat); 1888 if(stat == kOfxStatOK) { 1889 std::cout << ": ("<<rod.x1<<","<<rod.y1<<","<<rod.x2<<","<<rod.y2<<")"; 1890 } 1891 std::cout << std::endl; 1892 # endif 1893 1894 return stat; 1895 } 1896 1897 /// get the region of interest for each input and return it in the given std::map getRegionOfInterestAction(OfxTime time,OfxPointD renderScale,int view,const OfxRectD & roi,std::map<ClipInstance *,OfxRectD> & rois)1898 OfxStatus Instance::getRegionOfInterestAction(OfxTime time, 1899 OfxPointD renderScale, 1900 #ifdef OFX_EXTENSIONS_NUKE 1901 int view, 1902 #endif 1903 const OfxRectD &roi, 1904 std::map<ClipInstance *, OfxRectD>& rois) 1905 { 1906 if ( OFX::IsNaN(time) ) { 1907 return kOfxStatFailed; 1908 } 1909 OfxStatus stat = kOfxStatReplyDefault; 1910 1911 // reset the map 1912 rois.clear(); 1913 1914 // If an effect does not support tiles, it cannot *render* tiles, but it still may implement 1915 // kOfxImageEffectActionGetRegionsOfInterest. For example, if an input clip is not needed, it can 1916 // set the roi to an empty region on that input. On it can set the roi on each input to the 1917 // renderwindow instead of the input region of definition. 1918 // The only difference between effects that support tiles and thos that don't is the defaut 1919 // region set on each input: 1920 // - for effects that support tiles, it is the renderwindow 1921 // - for effect that don't, it is the region of definition of the input clip 1922 // 1923 // Same goes for the input clips: if an input clip does not support tiles, then set the default 1924 // RoI for this clip to its RoD, but still call action and let the effect have the final decision. 1925 bool supportstiles = supportsTiles(); 1926 1927 /// set up the in args 1928 static const Property::PropSpec inStuff[] = { 1929 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 1930 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 1931 { kOfxImageEffectPropRegionOfInterest , Property::eDouble, 4, true, 0 }, 1932 # ifdef OFX_EXTENSIONS_NUKE 1933 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 1934 # endif 1935 Property::propSpecEnd 1936 }; 1937 Property::Set inArgs(inStuff); 1938 1939 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 1940 inArgs.setDoubleProperty(kOfxPropTime,time); 1941 inArgs.setDoublePropertyN(kOfxImageEffectPropRegionOfInterest, &roi.x1, 4); 1942 # ifdef OFX_EXTENSIONS_NUKE 1943 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 1944 # endif 1945 1946 Property::Set outArgs; 1947 for (std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 1948 it!=_clips.end(); 1949 ++it) { 1950 if (!it->second->isOutput() || 1951 # ifdef OFX_EXTENSIONS_TUTTLE 1952 getContext() == kOfxImageEffectContextReader || 1953 # endif 1954 getContext() == kOfxImageEffectContextGenerator) { 1955 Property::PropSpec s; 1956 std::string name = "OfxImageClipPropRoI_"+it->first; 1957 1958 s.name = name.c_str(); 1959 s.type = Property::eDouble; 1960 s.dimension = 4; 1961 s.readonly = false; 1962 s.defaultValue = ""; 1963 outArgs.createProperty(s); 1964 1965 /// initialise to the default 1966 if (supportstiles && it->second->supportsTiles()) { 1967 outArgs.setDoublePropertyN(s.name, &roi.x1, 4); 1968 } else { 1969 OfxRectD rod = roi; 1970 // needed to be able to fetch the RoD 1971 if (it->second->isOutput() || it->second->getConnected()) { 1972 # ifdef OFX_EXTENSIONS_NUKE 1973 rod = it->second->getRegionOfDefinition(time, view); 1974 # else 1975 rod = it->second->getRegionOfDefinition(time); 1976 # endif 1977 } 1978 outArgs.setDoublePropertyN(s.name, &rod.x1, 4); 1979 } 1980 } 1981 } 1982 1983 # ifdef OFX_DEBUG_ACTIONS 1984 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 1985 const char* id = ofxp->pluginIdentifier; 1986 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetRegionsOfInterest<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"),("<<roi.x1<<","<<roi.y1<<","<<roi.x2<<","<<roi.y2<<"))"<<std::endl; 1987 # endif 1988 /// call the action 1989 stat = mainEntry(kOfxImageEffectActionGetRegionsOfInterest, 1990 this->getHandle(), 1991 &inArgs, 1992 &outArgs); 1993 1994 # ifdef OFX_DEBUG_ACTIONS 1995 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetRegionsOfInterest<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"),("<<roi.x1<<","<<roi.y1<<","<<roi.x2<<","<<roi.y2<<"))->"<<StatStr(stat); 1996 if (stat == kOfxStatOK) { 1997 std::cout << ": "; 1998 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 1999 it!=_clips.end(); 2000 ++it) { 2001 std::string name = "OfxImageClipPropRoI_"+it->first; 2002 OfxRectD thisRoi; 2003 thisRoi.x1 = outArgs.getDoubleProperty(name,0); 2004 thisRoi.y1 = outArgs.getDoubleProperty(name,1); 2005 thisRoi.x2 = outArgs.getDoubleProperty(name,2); 2006 thisRoi.y2 = outArgs.getDoubleProperty(name,3); 2007 std::cout << it->first << "->("<<thisRoi.x1<<","<<thisRoi.y1<<","<<thisRoi.x2<<","<<thisRoi.y2<<") "; 2008 } 2009 } 2010 std::cout << std::endl; 2011 # endif 2012 // get the results 2013 for (std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2014 it!=_clips.end(); 2015 ++it) { 2016 if (!it->second->isOutput() || 2017 #ifdef OFX_EXTENSIONS_TUTTLE 2018 getContext() == kOfxImageEffectContextReader || 2019 #endif 2020 getContext() == kOfxImageEffectContextGenerator) { 2021 if (it->second->isOutput() || it->second->getConnected()) { // needed to be able to fetch the RoD 2022 2023 std::string name = "OfxImageClipPropRoI_"+it->first; 2024 OfxRectD thisRoi; 2025 thisRoi.x1 = outArgs.getDoubleProperty(name,0); 2026 thisRoi.y1 = outArgs.getDoubleProperty(name,1); 2027 thisRoi.x2 = outArgs.getDoubleProperty(name,2); 2028 thisRoi.y2 = outArgs.getDoubleProperty(name,3); 2029 2030 // and DON'T clamp it to the clip's rod 2031 // We cannot clip it against the RoD because the RoI may be used for frames 2032 // at different a time or view than the current time and view passed to this action 2033 // which would result in a wrong clipping. Unfortunately only the implementation of 2034 // the host can do the correct clipping. 2035 //thisRoi = Clamp(thisRoi, rod); 2036 rois[it->second] = thisRoi; 2037 } 2038 } 2039 } 2040 return stat; 2041 } 2042 2043 #ifdef OFX_EXTENSIONS_NUKE getClipComponentsAction(OfxTime time,int view,ComponentsMap & clipComponents,ClipInstance * & passThroughClip,OfxTime & passThroughTime,int & passThroughView)2044 OfxStatus Instance::getClipComponentsAction(OfxTime time, 2045 int view, 2046 ComponentsMap& clipComponents, 2047 ClipInstance*& passThroughClip, 2048 OfxTime& passThroughTime, 2049 int& passThroughView) 2050 { 2051 if ( OFX::IsNaN(time) ) { 2052 return kOfxStatFailed; 2053 } 2054 OfxStatus stat = kOfxStatReplyDefault; 2055 2056 2057 Property::PropSpec inStuff[] = { 2058 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 2059 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 2060 Property::propSpecEnd 2061 }; 2062 Property::Set inArgs(inStuff); 2063 inArgs.setDoubleProperty(kOfxPropTime,time); 2064 2065 2066 Property::PropSpec outStuff[] = { 2067 { kFnOfxImageEffectPropPassThroughClip, Property::eString, 1, false, "" }, 2068 { kFnOfxImageEffectPropPassThroughTime, Property::eDouble, 1, false, "0" }, 2069 { kFnOfxImageEffectPropPassThroughView, Property::eInt, 1, false, "0" }, 2070 Property::propSpecEnd 2071 }; 2072 Property::Set outArgs(outStuff); 2073 2074 outArgs.setDoubleProperty(kFnOfxImageEffectPropPassThroughTime,time); 2075 outArgs.setIntProperty(kFnOfxImageEffectPropPassThroughView, view); 2076 2077 bool passThroughSet = false; 2078 ClipInstance* firstNonOptional = 0; 2079 2080 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2081 it!=_clips.end(); 2082 ++it) { 2083 2084 if (it->first == kOfxImageEffectSimpleSourceClipName) { 2085 outArgs.setStringProperty(kFnOfxImageEffectPropPassThroughClip, it->first); 2086 passThroughSet = true; 2087 } else if (it->first == "A" && !it->second->isOptional()) { 2088 outArgs.setStringProperty(kFnOfxImageEffectPropPassThroughClip, it->first); 2089 passThroughSet = true; 2090 } 2091 2092 if (!passThroughSet && !it->second->isOptional()) { 2093 firstNonOptional = it->second; 2094 } 2095 Property::PropSpec s; 2096 std::string name = kFnOfxImageEffectActionGetClipComponentsPropString + it->first; 2097 2098 s.name = name.c_str(); 2099 s.type = Property::eString; 2100 s.dimension = 0; 2101 s.readonly = false; 2102 s.defaultValue = ""; 2103 outArgs.createProperty(s); 2104 2105 } 2106 if (firstNonOptional && !passThroughSet) { 2107 outArgs.setStringProperty(kFnOfxImageEffectPropPassThroughClip, firstNonOptional->getName()); 2108 } 2109 2110 # ifdef OFX_DEBUG_ACTIONS 2111 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2112 const char* id = ofxp->pluginIdentifier; 2113 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetClipComponents<<"("<<time<<"," << view << ")"<<std::endl; 2114 # endif 2115 2116 stat = mainEntry(kFnOfxImageEffectActionGetClipComponents, 2117 this->getHandle(), 2118 &inArgs, 2119 &outArgs); 2120 2121 # ifdef OFX_DEBUG_ACTIONS 2122 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetClipComponents<<"("<<time<<"," << view << ")->"<<StatStr(stat); 2123 if (stat == kOfxStatOK) { 2124 std::cout << ": "; 2125 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2126 it!=_clips.end(); 2127 ++it) { 2128 std::string name = kFnOfxImageEffectActionGetClipComponentsPropString + it->first; 2129 std::cout << it->first << "->["; 2130 2131 int nRanges = outArgs.getDimension(name); 2132 for(int r=0;r<nRanges;++r){ 2133 std::string component = outArgs.getStringProperty(name,r); 2134 std::cout <<"("<< component <<")"; 2135 if (r < nRanges-1) { 2136 std::cout << ","; 2137 } 2138 } 2139 std::cout << "]"; 2140 2141 } 2142 } 2143 std::cout << std::endl; 2144 # endif 2145 2146 if (stat == kOfxStatOK) { 2147 2148 std::string passthroughClipName = outArgs.getStringProperty(kFnOfxImageEffectPropPassThroughClip); 2149 2150 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2151 it!=_clips.end(); 2152 ++it) { 2153 ClipInstance *clip = it->second; 2154 std::string name = kFnOfxImageEffectActionGetClipComponentsPropString + it->first; 2155 int nRanges = outArgs.getDimension(name); 2156 std::list<std::string> components; 2157 for (int r = 0 ; r < nRanges; ++r) { 2158 std::string component = outArgs.getStringProperty(name,r); 2159 components.push_back(component); 2160 } 2161 clipComponents.insert(std::make_pair(clip, components)); 2162 2163 if (it->first == passthroughClipName) { 2164 passThroughClip = it->second; 2165 } 2166 } 2167 2168 passThroughTime = outArgs.getDoubleProperty(kFnOfxImageEffectPropPassThroughTime); 2169 passThroughView = outArgs.getIntProperty(kFnOfxImageEffectPropPassThroughView); 2170 } 2171 return stat; 2172 } 2173 getFrameViewsNeeded(OfxTime time,int view,ViewsRangeMap & rangeMap)2174 OfxStatus Instance::getFrameViewsNeeded(OfxTime time, 2175 int view, 2176 ViewsRangeMap& rangeMap) 2177 { 2178 if ( OFX::IsNaN(time) ) { 2179 return kOfxStatFailed; 2180 } 2181 OfxStatus stat = kOfxStatReplyDefault; 2182 Property::Set outArgs; 2183 2184 2185 Property::PropSpec inStuff[] = { 2186 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 2187 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 2188 Property::propSpecEnd 2189 }; 2190 Property::Set inArgs(inStuff); 2191 inArgs.setDoubleProperty(kOfxPropTime, time); 2192 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 2193 2194 for (std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2195 it!=_clips.end(); 2196 ++it) { 2197 if (!it->second->isOutput()) { 2198 Property::PropSpec s; 2199 std::string name = "OfxImageClipPropFrameRangeView_" + it->first; 2200 2201 s.name = name.c_str(); 2202 s.type = Property::eDouble; 2203 s.dimension = 0; 2204 s.readonly = false; 2205 s.defaultValue = ""; 2206 outArgs.createProperty(s); 2207 outArgs.setDoubleProperty(name, time, 0); 2208 outArgs.setDoubleProperty(name, time, 1); 2209 outArgs.setDoubleProperty(name, view, 2); 2210 } 2211 } 2212 2213 # ifdef OFX_DEBUG_ACTIONS 2214 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2215 const char* id = ofxp->pluginIdentifier; 2216 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetFrameViewsNeeded<<"("<<time<<"," << view << ")"<<std::endl; 2217 # endif 2218 2219 stat = mainEntry(kFnOfxImageEffectActionGetFrameViewsNeeded, 2220 this->getHandle(), 2221 &inArgs, 2222 &outArgs); 2223 2224 # ifdef OFX_DEBUG_ACTIONS 2225 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kFnOfxImageEffectActionGetFrameViewsNeeded<<"("<<time<<"," << view << ")->"<<StatStr(stat); 2226 if (stat == kOfxStatOK) { 2227 std::cout << ": "; 2228 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2229 it!=_clips.end(); 2230 ++it) { 2231 std::string name = "OfxImageClipPropFrameRangeView_" + it->first; 2232 std::cout << it->first << "->["; 2233 2234 int nRanges = outArgs.getDimension(name); 2235 for(int r=0;r<nRanges;){ 2236 double min = outArgs.getDoubleProperty(name,r); 2237 double max = outArgs.getDoubleProperty(name,r+1); 2238 int view = (int)outArgs.getDoubleProperty(name, r+2); 2239 r += 3; 2240 std::cout <<"("<< min <<"," <<max<<","<<view <<")"; 2241 if (r < nRanges-1) { 2242 std::cout << ","; 2243 } 2244 } 2245 std::cout << "]"; 2246 2247 } 2248 } 2249 std::cout << std::endl; 2250 # endif 2251 2252 OfxRangeD defaultRange; 2253 defaultRange.min = 2254 defaultRange.max = time; 2255 int defaultView = view; 2256 2257 std::vector<OfxRangeD> defaultRangeV; 2258 defaultRangeV.push_back(defaultRange); 2259 std::map<int,std::vector<OfxRangeD> > defaultFrameViewMap; 2260 defaultFrameViewMap.insert(std::make_pair(defaultView, defaultRangeV)); 2261 2262 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2263 it!=_clips.end(); 2264 ++it) { 2265 2266 if (it->second->isOutput()) { 2267 continue; 2268 } 2269 2270 ClipInstance *clip = it->second; 2271 if (stat != kOfxStatOK) { 2272 rangeMap.insert(std::make_pair(clip, defaultFrameViewMap)); 2273 } else { 2274 2275 std::map<int,std::vector<OfxRangeD> > frameViewMap; 2276 2277 std::string name = "OfxImageClipPropFrameRangeView_" + it->first; 2278 int nRanges = outArgs.getDimension(name); 2279 for (int r = 0 ; r < nRanges; ){ 2280 OfxRangeD range; 2281 range.min = outArgs.getDoubleProperty(name,r); 2282 range.max = outArgs.getDoubleProperty(name,r+1); 2283 int view = (int)outArgs.getDoubleProperty(name, r+2); 2284 r += 3; 2285 2286 2287 std::map<int,std::vector<OfxRangeD> >::iterator foundView = frameViewMap.find(view); 2288 if (foundView != frameViewMap.end()) { 2289 foundView->second.push_back(range); 2290 } else { 2291 std::vector<OfxRangeD> rangeV; 2292 rangeV.push_back(range); 2293 frameViewMap.insert(std::make_pair(view, rangeV)); 2294 } 2295 2296 } 2297 rangeMap.insert(std::make_pair(clip, frameViewMap)); 2298 } 2299 } 2300 return stat; 2301 } 2302 #endif 2303 2304 //////////////////////////////////////////////////////////////////////////////// 2305 /// see how many frames are needed from each clip to render the indicated frame getFrameNeededAction(OfxTime time,RangeMap & rangeMap)2306 OfxStatus Instance::getFrameNeededAction(OfxTime time, 2307 RangeMap &rangeMap) 2308 { 2309 if ( OFX::IsNaN(time) ) { 2310 return kOfxStatFailed; 2311 } 2312 OfxStatus stat = kOfxStatReplyDefault; 2313 Property::Set outArgs; 2314 2315 if(temporalAccess()) { 2316 static const Property::PropSpec inStuff[] = { 2317 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 2318 #ifdef OFX_EXTENSIONS_NUKE 2319 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 2320 #endif 2321 Property::propSpecEnd 2322 }; 2323 Property::Set inArgs(inStuff); 2324 inArgs.setDoubleProperty(kOfxPropTime,time); 2325 2326 2327 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2328 it!=_clips.end(); 2329 ++it) { 2330 if(!it->second->isOutput()) { 2331 Property::PropSpec s; 2332 std::string name = "OfxImageClipPropFrameRange_"+it->first; 2333 2334 s.name = name.c_str(); 2335 s.type = Property::eDouble; 2336 s.dimension = 0; 2337 s.readonly = false; 2338 s.defaultValue = ""; 2339 outArgs.createProperty(s); 2340 /// intialise it to the current frame 2341 outArgs.setDoubleProperty(name, time, 0); 2342 outArgs.setDoubleProperty(name, time, 1); 2343 } 2344 } 2345 2346 # ifdef OFX_DEBUG_ACTIONS 2347 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2348 const char* id = ofxp->pluginIdentifier; 2349 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetFramesNeeded<<"("<<time<<")"<<std::endl; 2350 # endif 2351 stat = mainEntry(kOfxImageEffectActionGetFramesNeeded, 2352 this->getHandle(), 2353 &inArgs, 2354 &outArgs); 2355 # ifdef OFX_DEBUG_ACTIONS 2356 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetFramesNeeded<<"("<<time<<")->"<<StatStr(stat); 2357 if (stat == kOfxStatOK) { 2358 std::cout << ": "; 2359 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2360 it!=_clips.end(); 2361 ++it) { 2362 ClipInstance *clip = it->second; 2363 2364 if(!clip->isOutput()) { 2365 std::string name = "OfxImageClipPropFrameRange_"+it->first; 2366 std::cout << it->first << "->["; 2367 2368 int nRanges = outArgs.getDimension(name); 2369 for(int r=0;r<nRanges;){ 2370 double min = outArgs.getDoubleProperty(name,r); 2371 double max = outArgs.getDoubleProperty(name,r+1); 2372 r += 2; 2373 std::cout <<"("<<min<<","<<max<<")"; 2374 if (r < nRanges-1) { 2375 std::cout << ","; 2376 } 2377 } 2378 std::cout << "]"; 2379 } 2380 } 2381 } 2382 std::cout << std::endl; 2383 # endif 2384 } 2385 2386 OfxRangeD defaultRange; 2387 defaultRange.min = 2388 defaultRange.max = time; 2389 2390 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2391 it!=_clips.end(); 2392 ++it) { 2393 ClipInstance *clip = it->second; 2394 2395 if(!clip->isOutput()) { 2396 if(stat != kOfxStatOK) { 2397 rangeMap[clip].push_back(defaultRange); 2398 } 2399 else { 2400 std::string name = "OfxImageClipPropFrameRange_"+it->first; 2401 2402 int nRanges = outArgs.getDimension(name); 2403 if(nRanges%2 != 0) 2404 return kOfxStatFailed; // bad! needs to be divisible by 2 2405 2406 if(nRanges == 0) { 2407 rangeMap[clip].push_back(defaultRange); 2408 } 2409 else { 2410 for(int r=0;r<nRanges;){ 2411 double min = outArgs.getDoubleProperty(name,r); 2412 double max = outArgs.getDoubleProperty(name,r+1); 2413 r += 2; 2414 2415 OfxRangeD range; 2416 range.min = min; 2417 range.max = max; 2418 rangeMap[clip].push_back(range); 2419 } 2420 } 2421 } 2422 } 2423 } 2424 2425 return stat; 2426 } 2427 isIdentityAction(OfxTime & time,const std::string & field,const OfxRectI & renderRoI,OfxPointD renderScale,int & view,std::string & plane,std::string & clip)2428 OfxStatus Instance::isIdentityAction(OfxTime &time, 2429 const std::string & field, 2430 const OfxRectI &renderRoI, 2431 OfxPointD renderScale, 2432 #ifdef OFX_EXTENSIONS_NUKE 2433 int& view, 2434 std::string& plane, 2435 #endif 2436 std::string &clip) 2437 { 2438 if ( OFX::IsNaN(time) ) { 2439 return kOfxStatFailed; 2440 } 2441 static const Property::PropSpec inStuff[] = { 2442 { kOfxPropTime, Property::eDouble, 1, true, "0" }, 2443 { kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" }, 2444 { kOfxImageEffectPropRenderWindow, Property::eInt, 4, true, "0" }, 2445 { kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" }, 2446 #ifdef OFX_EXTENSIONS_NUKE 2447 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 2448 { kOfxImageEffectPropIdentityPlane, Property::eString, 1, true, ""}, 2449 #endif 2450 Property::propSpecEnd 2451 }; 2452 2453 static const Property::PropSpec outStuff[] = { 2454 { kOfxPropTime, Property::eDouble, 1, false, "0.0" }, 2455 { kOfxPropName, Property::eString, 1, false, "" }, 2456 #ifdef OFX_EXTENSIONS_NUKE 2457 { kFnOfxImageEffectPropView, Property::eInt, 1, true, "0" }, 2458 { kOfxImageEffectPropIdentityPlane, Property::eString, 1, true, ""}, 2459 #endif 2460 Property::propSpecEnd 2461 }; 2462 2463 Property::Set inArgs(inStuff); 2464 2465 inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field); 2466 inArgs.setDoubleProperty(kOfxPropTime,time); 2467 inArgs.setIntPropertyN(kOfxImageEffectPropRenderWindow, &renderRoI.x1, 4); 2468 inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2); 2469 #ifdef OFX_EXTENSIONS_NUKE 2470 inArgs.setIntProperty(kFnOfxImageEffectPropView, view); 2471 inArgs.setStringProperty(kOfxImageEffectPropIdentityPlane, plane); 2472 #endif 2473 2474 Property::Set outArgs(outStuff); 2475 #ifdef OFX_EXTENSIONS_NUKE 2476 // set the default value on outArgs for backward compatibility 2477 outArgs.setIntProperty(kFnOfxImageEffectPropView, view); 2478 outArgs.setStringProperty(kOfxImageEffectPropIdentityPlane, plane); 2479 #endif 2480 2481 # ifdef OFX_DEBUG_ACTIONS 2482 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2483 const char* id = ofxp->pluginIdentifier; 2484 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionIsIdentity<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl; 2485 # endif 2486 outArgs.setDoubleProperty(kOfxPropTime,time); 2487 2488 OfxStatus st = mainEntry(kOfxImageEffectActionIsIdentity, 2489 this->getHandle(), 2490 &inArgs, 2491 &outArgs); 2492 2493 # ifdef OFX_DEBUG_ACTIONS 2494 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionIsIdentity<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st); 2495 if(st==kOfxStatOK){ 2496 std::cout << ": "<<outArgs.getDoubleProperty(kOfxPropTime)<<","<<outArgs.getStringProperty(kOfxPropName); 2497 } 2498 std::cout<<std::endl; 2499 # endif 2500 2501 if(st==kOfxStatOK){ 2502 time = outArgs.getDoubleProperty(kOfxPropTime); 2503 clip = outArgs.getStringProperty(kOfxPropName); 2504 #ifdef OFX_EXTENSIONS_NUKE 2505 view = outArgs.getIntProperty(kFnOfxImageEffectPropView); 2506 plane = outArgs.getStringProperty(kOfxImageEffectPropIdentityPlane); 2507 #endif 2508 } 2509 2510 return st; 2511 } 2512 2513 /// Get whether the component is a supported 'chromatic' component (RGBA or alpha) in 2514 /// the base API. 2515 /// Override this if you have extended your chromatic colour types (eg RGB) and want 2516 /// the clip preferences logic to still work isChromaticComponent(const std::string & str) const2517 bool Instance::isChromaticComponent(const std::string &str) const 2518 { 2519 if(str == kOfxImageComponentRGBA) 2520 return true; 2521 if(str == kOfxImageComponentRGB) 2522 return true; 2523 # ifdef OFX_EXTENSIONS_NATRON 2524 if(str == kNatronOfxImageComponentXY) 2525 return true; 2526 # endif 2527 if(str == kOfxImageComponentAlpha) 2528 return true; 2529 return false; 2530 } 2531 2532 /// function to check for multiple bit depth support 2533 /// The answer will depend on host, plugin and context canCurrentlyHandleMultipleClipDepths() const2534 bool Instance::canCurrentlyHandleMultipleClipDepths() const 2535 { 2536 /// does the host support 'em 2537 bool hostSupports = gImageEffectHost->getProperties().getIntProperty(kOfxImageEffectPropSupportsMultipleClipDepths) != 0;; 2538 2539 /// does the plug-in support 'em 2540 bool pluginSupports = supportsMultipleClipDepths(); 2541 2542 /// no support, so no 2543 if(!hostSupports || !pluginSupports) 2544 return false; 2545 2546 /// if filter context, no support, tempted to change this though 2547 if(_context == kOfxImageEffectContextFilter) 2548 return false; 2549 2550 /// if filter context, no support 2551 if(_context == kOfxImageEffectContextGenerator || 2552 _context == kOfxImageEffectContextTransition || 2553 _context == kOfxImageEffectContextPaint || 2554 _context == kOfxImageEffectContextRetimer) 2555 return false; 2556 2557 /// OK we're cool 2558 return true; 2559 } 2560 2561 /// Setup the default clip preferences on the clips setDefaultClipPreferences()2562 void Instance::setDefaultClipPreferences() 2563 { 2564 /// is there multiple bit depth support? Depends on host, plugin and context 2565 bool multiBitDepth = canCurrentlyHandleMultipleClipDepths(); 2566 2567 /// OK find the deepest chromatic component on our input clips and the one with the 2568 /// most components 2569 bool hasSetCompsAndDepth = false; 2570 std::string deepestBitDepth = kOfxBitDepthNone; 2571 std::string mostComponents = kOfxImageComponentNone; 2572 double frameRate = getFrameRate(); //< default to the project frame rate 2573 std::string premult; 2574 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2575 it!=_clips.end(); 2576 ++it) { 2577 ClipInstance *clip = it->second; 2578 2579 if(!clip->isOutput()) { 2580 bool connected = clip->getConnected(); 2581 2582 if (connected) { 2583 frameRate = Maximum(frameRate, clip->getFrameRate()); 2584 } 2585 2586 std::string rawComp = clip->getUnmappedComponents(); 2587 rawComp = clip->findSupportedComp(rawComp); // turn that into a comp the plugin expects on that clip 2588 2589 const std::string &rawDepth = clip->getUnmappedBitDepth(); 2590 const std::string &rawPreMult = clip->getPremult(); 2591 2592 if(isChromaticComponent(rawComp)) { 2593 // Note: first chromatic input gives the default output premult too, even if not connected 2594 // (else the output of generators may be opaque even if the host default is premultiplied) 2595 if(rawComp == kOfxImageComponentRGBA && (connected || premult.empty())) { 2596 if(rawPreMult == kOfxImagePreMultiplied) 2597 premult = kOfxImagePreMultiplied; 2598 else if(rawPreMult == kOfxImageUnPreMultiplied && premult != kOfxImagePreMultiplied) 2599 premult = kOfxImageUnPreMultiplied; 2600 } 2601 2602 if(connected) { 2603 //Update deepest bitdepth and most components only if the infos are relevant, i.e: only if the clip is connected 2604 hasSetCompsAndDepth = true; 2605 deepestBitDepth = FindDeepestBitDepth(deepestBitDepth, rawDepth); 2606 bool mostIsAlpha = (mostComponents == kOfxImageComponentAlpha); 2607 bool rawIsAlpha = (rawComp == kOfxImageComponentAlpha); 2608 if (mostIsAlpha != rawIsAlpha) { 2609 // one is alpha, the other is anything else than just alpha: the union is RGBA 2610 mostComponents = kOfxImageComponentRGBA; 2611 } 2612 mostComponents = findMostChromaticComponents(mostComponents, rawComp); 2613 } 2614 } 2615 } 2616 } 2617 if (!hasSetCompsAndDepth) { 2618 mostComponents = kOfxImageComponentRGBA; 2619 deepestBitDepth = kOfxBitDepthFloat; 2620 } 2621 2622 /// set some stuff up 2623 _outputFrameRate = frameRate; 2624 _outputFielding = getDefaultOutputFielding(); 2625 _continuousSamples = false; 2626 _frameVarying = false; 2627 2628 /// now find the best depth that the plugin supports 2629 deepestBitDepth = bestSupportedDepth(deepestBitDepth); 2630 2631 /// now add the clip gubbins to the out args 2632 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2633 it!=_clips.end(); 2634 ++it) { 2635 ClipInstance *clip = it->second; 2636 2637 std::string comp, depth; 2638 2639 std::string rawComp = clip->getUnmappedComponents(); 2640 rawComp = clip->findSupportedComp(rawComp); // turn that into a comp the plugin expects on that clip 2641 const std::string &rawDepth = clip->getUnmappedBitDepth(); 2642 2643 if(isChromaticComponent(rawComp)) { 2644 2645 if(clip->isOutput() || clip->isOptional()) { 2646 // "Optional input clips can always have their component types remapped" 2647 // http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#id482755 2648 depth = deepestBitDepth; 2649 comp = clip->findSupportedComp(mostComponents); 2650 2651 clip->setPixelDepth(depth); 2652 clip->setComponents(comp); 2653 if(clip->isOutput() && premult.empty() && 2654 (comp == kOfxImageComponentRGBA || comp == kOfxImageComponentAlpha)) { 2655 premult = kOfxImagePreMultiplied; 2656 } 2657 } 2658 else { 2659 comp = rawComp; 2660 depth = multiBitDepth ? bestSupportedDepth(rawDepth) : deepestBitDepth; 2661 2662 clip->setPixelDepth(depth); 2663 clip->setComponents(comp); 2664 } 2665 } 2666 else { 2667 /// hmm custom component type, don't touch it and pass it through 2668 clip->setPixelDepth(rawDepth); 2669 clip->setComponents(rawComp); 2670 } 2671 } 2672 // default to a reasonable value if there is no input 2673 if (premult.empty()) { 2674 premult = kOfxImageOpaque; 2675 } 2676 // set output premultiplication 2677 _outputPreMultiplication = premult; 2678 } 2679 2680 /// Initialise the clip preferences arguments, override this to do 2681 /// stuff with wierd components etc... setupClipPreferencesArgs(Property::Set & outArgs)2682 void Instance::setupClipPreferencesArgs(Property::Set &outArgs) 2683 { 2684 /// reset all the clip prefs stuff to their defaults 2685 setDefaultClipPreferences(); 2686 2687 static const Property::PropSpec clipPrefsStuffs []= 2688 { 2689 { kOfxImageEffectPropFrameRate, Property::eDouble, 1, false, "1" }, 2690 { kOfxImageEffectPropPreMultiplication, Property::eString, 1, false, "" }, 2691 { kOfxImageClipPropFieldOrder, Property::eString, 1, false, "" }, 2692 { kOfxImageClipPropContinuousSamples, Property::eInt, 1, false, "0" }, 2693 { kOfxImageEffectFrameVarying, Property::eInt, 1, false, "0" }, 2694 #ifdef OFX_EXTENSIONS_NATRON 2695 { kOfxImageClipPropFormat, Property::eInt, 4, false, "0"}, 2696 #endif 2697 Property::propSpecEnd 2698 }; 2699 2700 outArgs.addProperties(clipPrefsStuffs); 2701 2702 /// set the default for those 2703 2704 /// is there multiple bit depth support? Depends on host, plugin and context 2705 bool multiBitDepth = canCurrentlyHandleMultipleClipDepths(); 2706 2707 outArgs.setStringProperty(kOfxImageClipPropFieldOrder, _outputFielding); 2708 outArgs.setStringProperty(kOfxImageEffectPropPreMultiplication, _outputPreMultiplication); 2709 2710 /// now add the clip gubbins to the out args 2711 double projectPAR = getProjectPixelAspectRatio(); 2712 2713 #ifdef OFX_EXTENSIONS_NATRON 2714 double projectExtent[2]; 2715 double projectOffset[2]; 2716 getProjectOffset(projectOffset[0], projectOffset[1]); 2717 getProjectExtent(projectExtent[0], projectExtent[1]); 2718 // Project format is in canonical coordinates, so divide by PAR 2719 if (projectPAR != 0.) { 2720 projectOffset[0] /= projectPAR; 2721 projectExtent[0] /= projectPAR; 2722 } 2723 bool outputFormatSet = false; 2724 OfxRectI outputFormat = { (int)(projectOffset[0] + 0.5), 2725 (int)(projectOffset[1] + 0.5), 2726 (int)(projectOffset[0] + projectExtent[0] + 0.5), 2727 (int)(projectOffset[1] + projectExtent[1] + 0.5)}; 2728 #endif 2729 2730 2731 2732 2733 bool multipleClipsPAR = supportsMultipleClipPARs(); 2734 /// get the PAR of inputs, if it has different PARs and the effect does not support multiple clips PAR, throw an exception 2735 double inputPar = 1.; 2736 2737 bool inputParSet = false; 2738 for (std::map<std::string, ClipInstance*>::iterator it2 = _clips.begin(); it2 != _clips.end(); ++it2) { 2739 if (!it2->second->isOutput() && it2->second->getConnected()) { 2740 if (!inputParSet) { 2741 inputPar = it2->second->getAspectRatio(); 2742 inputParSet = true; 2743 } else if (!multipleClipsPAR && inputPar != it2->second->getAspectRatio()) { 2744 // We have several inputs with different aspect ratio, which should be forbidden by the host. 2745 throw Property::Exception(kOfxStatErrValue); 2746 } 2747 #ifdef OFX_EXTENSIONS_NATRON 2748 if (!outputFormatSet && !it2->second->isOptional()) { 2749 outputFormat = it2->second->getFormat(); 2750 outputFormatSet = true; 2751 } 2752 #endif 2753 } 2754 } 2755 2756 2757 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2758 it!=_clips.end(); 2759 ++it) { 2760 ClipInstance *clip = it->second; 2761 2762 std::string componentParamName = "OfxImageClipPropComponents_"+it->first; 2763 std::string depthParamName = "OfxImageClipPropDepth_"+it->first; 2764 std::string parParamName = "OfxImageClipPropPAR_"+it->first; 2765 2766 Property::PropSpec specComp = {componentParamName.c_str(), Property::eString, 0, false, ""}; // note the support for multi-planar clips 2767 outArgs.createProperty(specComp); 2768 outArgs.setStringProperty(componentParamName.c_str(), clip->getComponents().c_str()); // as it is variable dimension, there is no default value, so we have to set it explicitly 2769 2770 Property::PropSpec specDep = {depthParamName.c_str(), Property::eString, 1, !multiBitDepth, clip->getPixelDepth().c_str()}; 2771 outArgs.createProperty(specDep); 2772 2773 Property::PropSpec specPAR = {parParamName.c_str(), Property::eDouble, 1, false, "1"}; 2774 outArgs.createProperty(specPAR); 2775 if (!clip->isOutput()) { 2776 // If the clip is input, use the same par for all inputs unless the plug-in supports multiple clips PAR 2777 double par; 2778 if (!multipleClipsPAR && inputParSet) { 2779 par = inputPar; 2780 } else if (multipleClipsPAR) { 2781 par = clip->getAspectRatio(); 2782 } else { 2783 par = projectPAR; 2784 } 2785 outArgs.setDoubleProperty(parParamName, par); 2786 } else { 2787 // If the clip is output we should propagate the pixel aspect ratio of the inputs 2788 outArgs.setDoubleProperty(parParamName, inputParSet ? inputPar : projectPAR); 2789 } 2790 } 2791 2792 //Set the output frame rate according to what input clips have. Several inputs with different frame rates should be 2793 //forbidden by the host. 2794 bool outputFrameRateSet = false; 2795 double outputFrameRate = _outputFrameRate; 2796 for (std::map<std::string, ClipInstance*>::iterator it2 = _clips.begin(); it2 != _clips.end(); ++it2) { 2797 if (!it2->second->isOutput() && it2->second->getConnected()) { 2798 if (!outputFrameRateSet) { 2799 outputFrameRate = it2->second->getFrameRate(); 2800 outputFrameRateSet = true; 2801 } else if (outputFrameRate != it2->second->getFrameRate()) { 2802 // We have several inputs with different frame rates 2803 throw Property::Exception(kOfxStatErrValue); 2804 } 2805 } 2806 } 2807 2808 outArgs.setDoubleProperty(kOfxImageEffectPropFrameRate, outputFrameRate); 2809 #ifdef OFX_EXTENSIONS_NATRON 2810 outArgs.setIntPropertyN(kOfxImageClipPropFormat, (const int*)&outputFormat.x1, 4); 2811 #endif 2812 2813 } 2814 2815 /// the idea here is the clip prefs live as active props on the effect 2816 /// and are set up by clip preferences. The action manages the clip 2817 /// preferences bits. We also monitor clip and param changes and 2818 /// flag when clip prefs is dirty. 2819 /// call the clip preferences action getClipPreferences()2820 bool Instance::getClipPreferences() 2821 { 2822 /// create the out args with the stuff that does not depend on individual clips 2823 Property::Set outArgs; 2824 2825 setupClipPreferencesArgs(outArgs); 2826 2827 2828 # ifdef OFX_DEBUG_ACTIONS 2829 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2830 const char* id = ofxp->pluginIdentifier; 2831 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetClipPreferences<<"()"<<std::endl; 2832 # endif 2833 OfxStatus st = mainEntry(kOfxImageEffectActionGetClipPreferences, 2834 this->getHandle(), 2835 0, 2836 &outArgs); 2837 # ifdef OFX_DEBUG_ACTIONS 2838 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetClipPreferences<<"()->"<<StatStr(st); 2839 # endif 2840 2841 if(st!=kOfxStatOK && st!=kOfxStatReplyDefault) { 2842 # ifdef OFX_DEBUG_ACTIONS 2843 std::cout << std::endl; 2844 # endif 2845 /// ouch 2846 return false; 2847 } 2848 2849 # ifdef OFX_DEBUG_ACTIONS 2850 std::cout << ": "; 2851 # endif 2852 /// OK, go pump the components/depths back into the clips themselves 2853 for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin(); 2854 it!=_clips.end(); 2855 ++it) { 2856 ClipInstance *clip = it->second; 2857 2858 std::string componentParamName = "OfxImageClipPropComponents_"+it->first; 2859 std::string depthParamName = "OfxImageClipPropDepth_"+it->first; 2860 std::string parParamName = "OfxImageClipPropPAR_"+it->first; 2861 2862 # ifdef OFX_DEBUG_ACTIONS 2863 std::cout << it->first<<"->"<<outArgs.getStringProperty(depthParamName)<<","<<outArgs.getStringProperty(componentParamName)<<","<<outArgs.getDoubleProperty(parParamName)<<" "; 2864 # endif 2865 2866 clip->setPixelDepth(outArgs.getStringProperty(depthParamName)); 2867 clip->setComponents(outArgs.getStringProperty(componentParamName)); 2868 //clip->setPixelAspect(outArgs.getDoubleProperty(parParamName)); 2869 } 2870 2871 _outputFrameRate = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRate); 2872 _outputFielding = outArgs.getStringProperty(kOfxImageClipPropFieldOrder); 2873 _outputPreMultiplication = outArgs.getStringProperty(kOfxImageEffectPropPreMultiplication); 2874 _continuousSamples = outArgs.getIntProperty(kOfxImageClipPropContinuousSamples) != 0; 2875 _frameVarying = outArgs.getIntProperty(kOfxImageEffectFrameVarying) != 0; 2876 # ifdef OFX_DEBUG_ACTIONS 2877 std::cout << _outputFrameRate<<","<<_outputFielding<<","<<_outputPreMultiplication<<","<<_continuousSamples<<","<<_frameVarying<<std::endl; 2878 # endif 2879 2880 _clipPrefsDirty = false; 2881 2882 return true; 2883 } 2884 2885 /// find the most chromatic components out of the two. Override this if you define 2886 /// more chromatic components findMostChromaticComponents(const std::string & a,const std::string & b) const2887 const std::string &Instance::findMostChromaticComponents(const std::string &a, const std::string &b) const 2888 { 2889 if(a == kOfxImageComponentNone) 2890 return b; 2891 if(a == kOfxImageComponentRGBA) 2892 return a; 2893 if(b == kOfxImageComponentRGBA) 2894 return b; 2895 if(a == kOfxImageComponentRGB) 2896 return a; 2897 if(b == kOfxImageComponentRGB) 2898 return b; 2899 return a; 2900 } 2901 2902 /// given the bit depth, find the best match for it. bestSupportedDepth(const std::string & depth) const2903 const std::string &Instance::bestSupportedDepth(const std::string &depth) const 2904 { 2905 static const std::string none(kOfxBitDepthNone); 2906 static const std::string bytes(kOfxBitDepthByte); 2907 static const std::string shorts(kOfxBitDepthShort); 2908 static const std::string halfs(kOfxBitDepthHalf); 2909 static const std::string floats(kOfxBitDepthFloat); 2910 2911 if(depth == none) 2912 return none; 2913 2914 if(isPixelDepthSupported(depth)) 2915 return depth; 2916 2917 if(depth == floats) { 2918 if(isPixelDepthSupported(shorts)) 2919 return shorts; 2920 if(isPixelDepthSupported(bytes)) 2921 return bytes; 2922 } 2923 2924 if(depth == halfs) { 2925 if(isPixelDepthSupported(floats)) 2926 return floats; 2927 if(isPixelDepthSupported(shorts)) 2928 return shorts; 2929 if(isPixelDepthSupported(bytes)) 2930 return bytes; 2931 } 2932 2933 if(depth == shorts) { 2934 if(isPixelDepthSupported(floats)) 2935 return floats; 2936 if(isPixelDepthSupported(bytes)) 2937 return bytes; 2938 } 2939 2940 if(depth == bytes) { 2941 if(isPixelDepthSupported(shorts)) 2942 return shorts; 2943 if(isPixelDepthSupported(floats)) 2944 return floats; 2945 } 2946 2947 /// WTF? Something wrong here 2948 return none; 2949 } 2950 2951 #ifdef OFX_EXTENSIONS_NATRON isInViewportParam(const std::string & paramName) const2952 bool Instance::isInViewportParam(const std::string& paramName) const 2953 { 2954 int nDim = getProps().getDimension(kNatronOfxImageEffectPropInViewerContextParamsOrder); 2955 for (int i = 0; nDim; ++i) { 2956 const std::string& p = getProps().getStringProperty(kNatronOfxImageEffectPropInViewerContextParamsOrder, i); 2957 if (paramName == p) { 2958 return true; 2959 } 2960 } 2961 return false; 2962 } 2963 #endif 2964 2965 /// get the interact description, this will also call describe on the interact getOverlayDescriptor(int bitDepthPerComponent,bool hasAlpha)2966 Interact::Descriptor &Instance::getOverlayDescriptor(int bitDepthPerComponent, bool hasAlpha) 2967 { 2968 return _descriptor->getOverlayDescriptor(bitDepthPerComponent, hasAlpha); 2969 } 2970 getTimeDomainAction(OfxRangeD & range)2971 OfxStatus Instance::getTimeDomainAction(OfxRangeD& range) 2972 { 2973 static const Property::PropSpec outStuff[] = { 2974 { kOfxImageEffectPropFrameRange , Property::eDouble, 2, false, "0.0" }, 2975 Property::propSpecEnd 2976 }; 2977 2978 Property::Set outArgs(outStuff); 2979 2980 # ifdef OFX_DEBUG_ACTIONS 2981 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 2982 const char* id = ofxp->pluginIdentifier; 2983 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetTimeDomain<<"()"<<std::endl; 2984 # endif 2985 OfxStatus st = mainEntry(kOfxImageEffectActionGetTimeDomain, 2986 this->getHandle(), 2987 0, 2988 &outArgs); 2989 # ifdef OFX_DEBUG_ACTIONS 2990 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxImageEffectActionGetTimeDomain<<"()->"<<StatStr(st); 2991 if (st == kOfxStatOK) { 2992 std::cout << ": ("<<outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,0)<<","<<outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,1)<<")"; 2993 } std::cout << std::endl; 2994 # endif 2995 if(st!=kOfxStatOK) return st; 2996 2997 range.min = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,0); 2998 range.max = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,1); 2999 3000 return kOfxStatOK; 3001 } 3002 3003 #ifdef OFX_SUPPORTS_DIALOG 3004 // OfxDialogSuite 3005 /// @see kOfxActionDialog dialog(void * instanceData)3006 OfxStatus Instance::dialog(void *instanceData) 3007 { 3008 static const Property::PropSpec inStuff[] = { 3009 { kOfxPropInstanceData, Property::ePointer, 1, true, NULL }, 3010 Property::propSpecEnd 3011 }; 3012 3013 Property::Set inArgs(inStuff); 3014 3015 inArgs.setPointerProperty(kOfxPropInstanceData, instanceData); 3016 3017 # ifdef OFX_DEBUG_ACTIONS 3018 OfxPlugin *ofxp = _plugin->getPluginHandle()->getOfxPlugin(); 3019 const char* id = ofxp->pluginIdentifier; 3020 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionDialog<<"("<<instanceData<<")"<<std::endl; 3021 # endif 3022 OfxStatus st = mainEntry(kOfxActionDialog, 3023 this->getHandle(), 3024 &inArgs, 3025 0); 3026 # ifdef OFX_DEBUG_ACTIONS 3027 std::cout << "OFX: "<<id<<"("<<(void*)ofxp<<")->"<<kOfxActionDialog<<"("<<instanceData<<")->"<<StatStr(st); 3028 std::cout << std::endl; 3029 # endif 3030 3031 return st; 3032 } 3033 #endif 3034 3035 /// implemented for Param::SetInstance paramChangedByPlugin(Param::Instance * param)3036 void Instance::paramChangedByPlugin(Param::Instance *param) 3037 { 3038 if (!_created) { 3039 // setValue() was probably called from kOfxActionCreateInstance 3040 // this is legal according to http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#SettingParams 3041 // but kOfxActionInstanceChanged should not be called according to the preconditions of http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#kOfxActionInstanceChanged 3042 return; 3043 } 3044 double frame = getFrameRecursive(); 3045 OfxPointD renderScale; getRenderScaleRecursive(renderScale.x, renderScale.y); 3046 3047 beginInstanceChangedAction(kOfxChangePluginEdited); 3048 paramInstanceChangedAction(param->getName(), kOfxChangePluginEdited, frame, renderScale); 3049 endInstanceChangedAction(kOfxChangePluginEdited); 3050 } 3051 3052 //////////////////////////////////////////////////////////////////////////////// 3053 //////////////////////////////////////////////////////////////////////////////// 3054 //////////////////////////////////////////////////////////////////////////////// 3055 /// The image effect suite functions getPropertySet(OfxImageEffectHandle h1,OfxPropertySetHandle * h2)3056 static OfxStatus getPropertySet(OfxImageEffectHandle h1, 3057 OfxPropertySetHandle *h2) 3058 { 3059 # ifdef OFX_DEBUG_PROPERTIES 3060 std::cout << "OFX: getPropertySet - " << h1 << " = ..."; 3061 # endif 3062 try { 3063 if (!h2) { 3064 # ifdef OFX_DEBUG_PROPERTIES 3065 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3066 # endif 3067 return kOfxStatErrBadHandle; 3068 } 3069 3070 Base *effectBase = reinterpret_cast<Base*>(h1); 3071 3072 if (!effectBase || !effectBase->verifyMagic()) { 3073 *h2 = NULL; 3074 3075 # ifdef OFX_DEBUG_PROPERTIES 3076 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3077 # endif 3078 return kOfxStatErrBadHandle; 3079 } 3080 3081 *h2 = effectBase->getProps().getHandle(); 3082 3083 # ifdef OFX_DEBUG_PROPERTIES 3084 std::cout << *h2 << ' ' << StatStr(kOfxStatOK) << std::endl; 3085 # endif 3086 return kOfxStatOK; 3087 } catch (...) { 3088 *h2 = NULL; 3089 3090 # ifdef OFX_DEBUG_PROPERTIES 3091 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3092 # endif 3093 return kOfxStatErrBadHandle; 3094 } 3095 } 3096 getParamSet(OfxImageEffectHandle h1,OfxParamSetHandle * h2)3097 static OfxStatus getParamSet(OfxImageEffectHandle h1, 3098 OfxParamSetHandle *h2) 3099 { 3100 # ifdef OFX_DEBUG_PARAMETERS 3101 std::cout << "OFX: getParamSet - " << h1 << " = ..."; 3102 # endif 3103 try { 3104 if (!h2) { 3105 return kOfxStatErrBadHandle; 3106 } 3107 3108 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(h1); 3109 3110 if (!effectBase || !effectBase->verifyMagic()) { 3111 *h2 = NULL; 3112 3113 # ifdef OFX_DEBUG_PARAMETERS 3114 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3115 # endif 3116 return kOfxStatErrBadHandle; 3117 } 3118 3119 ImageEffect::Descriptor *effectDescriptor = dynamic_cast<ImageEffect::Descriptor*>(effectBase); 3120 3121 if(effectDescriptor) { 3122 *h2 = effectDescriptor->getParamSetHandle(); 3123 3124 # ifdef OFX_DEBUG_PARAMETERS 3125 std::cout << *h2 << ' ' << StatStr(kOfxStatOK) << std::endl; 3126 # endif 3127 return kOfxStatOK; 3128 } 3129 3130 ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase); 3131 3132 if(effectInstance) { 3133 *h2 = effectInstance->getParamSetHandle(); 3134 3135 # ifdef OFX_DEBUG_PARAMETERS 3136 std::cout << *h2 << ' ' << StatStr(kOfxStatOK) << std::endl; 3137 # endif 3138 return kOfxStatOK; 3139 } 3140 3141 *h2 = NULL; 3142 3143 # ifdef OFX_DEBUG_PARAMETERS 3144 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3145 # endif 3146 return kOfxStatErrBadHandle; 3147 } catch (...) { 3148 *h2 = NULL; 3149 3150 # ifdef OFX_DEBUG_PARAMETERS 3151 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3152 # endif 3153 return kOfxStatErrBadHandle; 3154 } 3155 } 3156 clipDefine(OfxImageEffectHandle h1,const char * name,OfxPropertySetHandle * h2)3157 static OfxStatus clipDefine(OfxImageEffectHandle h1, 3158 const char *name, 3159 OfxPropertySetHandle *h2) 3160 { 3161 try { 3162 if (!h2) { 3163 return kOfxStatErrBadHandle; 3164 } 3165 3166 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(h1); 3167 3168 if (!effectBase || !effectBase->verifyMagic()) { 3169 *h2 = NULL; 3170 3171 return kOfxStatErrBadHandle; 3172 } 3173 3174 ImageEffect::Descriptor *effectDescriptor = dynamic_cast<ImageEffect::Descriptor*>(effectBase); 3175 3176 if(effectDescriptor){ 3177 ClipDescriptor *clip = effectDescriptor->defineClip(name); 3178 *h2 = clip->getPropHandle(); 3179 3180 return kOfxStatOK; 3181 } 3182 3183 *h2 = NULL; 3184 3185 return kOfxStatErrBadHandle; 3186 } catch (...) { 3187 *h2 = NULL; 3188 3189 return kOfxStatErrBadHandle; 3190 } 3191 } 3192 clipGetPropertySet(OfxImageClipHandle clip,OfxPropertySetHandle * propHandle)3193 static OfxStatus clipGetPropertySet(OfxImageClipHandle clip, 3194 OfxPropertySetHandle *propHandle){ 3195 # ifdef OFX_DEBUG_PROPERTIES 3196 std::cout << "OFX: clipGetPropertySet - " << clip << " = ..."; 3197 # endif 3198 try { 3199 if (!propHandle) { 3200 return kOfxStatErrBadHandle; 3201 } 3202 3203 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip); 3204 3205 if (!clipInstance || !clipInstance->verifyMagic()) { 3206 *propHandle = NULL; 3207 3208 # ifdef OFX_DEBUG_PROPERTIES 3209 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3210 # endif 3211 return kOfxStatErrBadHandle; 3212 } 3213 3214 *propHandle = clipInstance->getPropHandle(); 3215 # ifdef OFX_DEBUG_PROPERTIES 3216 std::cout << *propHandle << ' ' << StatStr(kOfxStatOK) << std::endl; 3217 # endif 3218 return kOfxStatOK; 3219 } catch (...) { 3220 *propHandle = NULL; 3221 3222 # ifdef OFX_DEBUG_PROPERTIES 3223 std::cout << ' ' << StatStr(kOfxStatErrBadHandle) << std::endl; 3224 # endif 3225 return kOfxStatErrBadHandle; 3226 } 3227 } 3228 clipGetImage(OfxImageClipHandle h1,OfxTime time,const OfxRectD * h2,OfxPropertySetHandle * h3)3229 static OfxStatus clipGetImage(OfxImageClipHandle h1, 3230 OfxTime time, 3231 const OfxRectD *h2, 3232 OfxPropertySetHandle *h3) 3233 { 3234 if ( OFX::IsNaN(time) ) { 3235 return kOfxStatFailed; 3236 } 3237 try { 3238 if (!h3) { 3239 return kOfxStatErrBadHandle; 3240 } 3241 3242 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(h1); 3243 3244 if (!clipInstance || !clipInstance->verifyMagic()) { 3245 *h3 = NULL; 3246 return kOfxStatErrBadHandle; 3247 } 3248 3249 Image* image = clipInstance->getImage(time,h2); 3250 if(!image) { 3251 *h3 = NULL; 3252 3253 return kOfxStatFailed; 3254 } 3255 3256 *h3 = image->getPropHandle(); 3257 3258 return kOfxStatOK; 3259 } catch (...) { 3260 *h3 = NULL; 3261 3262 return kOfxStatErrBadHandle; 3263 } 3264 } 3265 3266 #ifdef OFX_EXTENSIONS_VEGAS clipGetStereoscopicImage(OfxImageClipHandle h1,OfxTime time,int view,OfxRectD * h2,OfxPropertySetHandle * h3)3267 static OfxStatus clipGetStereoscopicImage(OfxImageClipHandle h1, 3268 OfxTime time, 3269 int view, 3270 OfxRectD *h2, 3271 OfxPropertySetHandle *h3) 3272 { 3273 if ( OFX::IsNaN(time) ) { 3274 return kOfxStatFailed; 3275 } 3276 try { 3277 if (!h3) { 3278 return kOfxStatErrBadHandle; 3279 } 3280 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(h1); 3281 3282 if (!clipInstance || !clipInstance->verifyMagic()) { 3283 *h3 = NULL; 3284 3285 return kOfxStatErrBadHandle; 3286 } 3287 3288 Image* image = clipInstance->getStereoscopicImage(time,view,h2); 3289 if(!image) { 3290 *h3 = NULL; 3291 3292 return kOfxStatFailed; 3293 } 3294 3295 *h3 = image->getPropHandle(); 3296 3297 return kOfxStatOK; 3298 } catch (...) { 3299 *h3 = NULL; 3300 3301 return kOfxStatErrBadHandle; 3302 } 3303 } 3304 #endif 3305 clipReleaseImage(OfxPropertySetHandle h1)3306 static OfxStatus clipReleaseImage(OfxPropertySetHandle h1) 3307 { 3308 try { 3309 Property::Set *pset = reinterpret_cast<Property::Set*>(h1); 3310 3311 if (!pset || !pset->verifyMagic()) { 3312 return kOfxStatErrBadHandle; 3313 } 3314 3315 Image *image = dynamic_cast<Image*>(pset); 3316 3317 if(image){ 3318 // clip::image has a virtual destructor for derived classes 3319 image->releaseReference(); 3320 3321 return kOfxStatOK; 3322 } 3323 3324 return kOfxStatErrBadHandle; 3325 } catch (...) { 3326 return kOfxStatErrBadHandle; 3327 } 3328 } 3329 clipGetHandle(OfxImageEffectHandle imageEffect,const char * name,OfxImageClipHandle * clip,OfxPropertySetHandle * propertySet)3330 static OfxStatus clipGetHandle(OfxImageEffectHandle imageEffect, 3331 const char *name, 3332 OfxImageClipHandle *clip, 3333 OfxPropertySetHandle *propertySet) 3334 { 3335 try { 3336 if (!clip) { 3337 return kOfxStatErrBadHandle; 3338 } 3339 3340 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(imageEffect); 3341 3342 if (!effectBase || !effectBase->verifyMagic()) { 3343 return kOfxStatErrBadHandle; 3344 } 3345 3346 ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(effectBase); 3347 3348 if(effectInstance){ 3349 ClipInstance* instance = effectInstance->getClip(name); 3350 if(!instance) 3351 return kOfxStatErrBadHandle; 3352 *clip = instance->getHandle(); 3353 if(propertySet) 3354 *propertySet = instance->getPropHandle(); 3355 return kOfxStatOK; 3356 } 3357 3358 return kOfxStatErrBadHandle; 3359 } catch (...) { 3360 return kOfxStatErrBadHandle; 3361 } 3362 } 3363 clipGetRegionOfDefinition(OfxImageClipHandle clip,OfxTime time,OfxRectD * bounds)3364 static OfxStatus clipGetRegionOfDefinition(OfxImageClipHandle clip, 3365 OfxTime time, 3366 OfxRectD *bounds) 3367 { 3368 if ( OFX::IsNaN(time) ) { 3369 return kOfxStatFailed; 3370 } 3371 try { 3372 if (!bounds) { 3373 return kOfxStatErrBadHandle; 3374 } 3375 3376 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip); 3377 3378 if (!clipInstance || !clipInstance->verifyMagic()) { 3379 bounds->x1 = bounds->y1 = bounds->x2 = bounds->y2 = 0.; 3380 3381 return kOfxStatErrBadHandle; 3382 } 3383 3384 *bounds = clipInstance->getRegionOfDefinition(time); 3385 if (bounds->x2 < bounds->x1 || bounds->y2 < bounds->y1) { 3386 // the RoD is invalid (empty is OK) 3387 3388 return kOfxStatFailed; 3389 } 3390 3391 return kOfxStatOK; 3392 } catch (...) { 3393 return kOfxStatErrBadHandle; 3394 } 3395 } 3396 3397 // should processing be aborted? abort(OfxImageEffectHandle imageEffect)3398 static int abort(OfxImageEffectHandle imageEffect) 3399 { 3400 try { 3401 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(imageEffect); 3402 3403 if (!effectBase || !effectBase->verifyMagic()) { 3404 return kOfxStatErrBadHandle; 3405 } 3406 3407 ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase); 3408 3409 if(effectInstance) 3410 return effectInstance->abort(); 3411 else 3412 return kOfxStatErrBadHandle; 3413 } catch (...) { 3414 return kOfxStatErrBadHandle; 3415 } 3416 } 3417 imageMemoryAlloc(OfxImageEffectHandle instanceHandle,size_t nBytes,OfxImageMemoryHandle * memoryHandle)3418 static OfxStatus imageMemoryAlloc(OfxImageEffectHandle instanceHandle, 3419 size_t nBytes, 3420 OfxImageMemoryHandle *memoryHandle) 3421 { 3422 try { 3423 if (!memoryHandle) { 3424 return kOfxStatErrBadHandle; 3425 } 3426 3427 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(instanceHandle); 3428 ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(effectBase); 3429 Memory::Instance* memory; 3430 3431 if(effectInstance){ 3432 3433 if (!effectInstance->verifyMagic()) { 3434 *memoryHandle = NULL; 3435 return kOfxStatErrBadHandle; 3436 } 3437 3438 memory = effectInstance->imageMemoryAlloc(nBytes); 3439 } 3440 else { 3441 memory = gImageEffectHost->imageMemoryAlloc(nBytes); 3442 } 3443 3444 if (memory) { 3445 *memoryHandle = memory->getHandle(); 3446 return kOfxStatOK; 3447 } else { 3448 *memoryHandle = NULL; 3449 return kOfxStatErrMemory; 3450 } 3451 } catch (std::bad_alloc) { 3452 *memoryHandle = NULL; 3453 return kOfxStatErrMemory; 3454 } catch (...) { 3455 *memoryHandle = NULL; 3456 return kOfxStatErrBadHandle; 3457 } 3458 } 3459 imageMemoryFree(OfxImageMemoryHandle memoryHandle)3460 static OfxStatus imageMemoryFree(OfxImageMemoryHandle memoryHandle){ 3461 try { 3462 Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle); 3463 3464 if(memoryInstance && memoryInstance->verifyMagic()) { 3465 if (memoryInstance->freeMem()) { 3466 delete memoryInstance; 3467 } 3468 return kOfxStatOK; 3469 } 3470 else 3471 return kOfxStatErrBadHandle; 3472 } catch (...) { 3473 return kOfxStatErrBadHandle; 3474 } 3475 } 3476 3477 static imageMemoryLock(OfxImageMemoryHandle memoryHandle,void ** returnedPtr)3478 OfxStatus imageMemoryLock(OfxImageMemoryHandle memoryHandle, 3479 void **returnedPtr){ 3480 try { 3481 if (!returnedPtr) { 3482 return kOfxStatErrBadHandle; 3483 } 3484 3485 Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle); 3486 3487 if(memoryInstance && memoryInstance->verifyMagic()) { 3488 memoryInstance->lock(); 3489 *returnedPtr = memoryInstance->getPtr(); 3490 3491 return (*returnedPtr) ? kOfxStatOK : kOfxStatErrMemory; 3492 } 3493 3494 *returnedPtr = NULL; 3495 3496 return kOfxStatErrBadHandle; 3497 } catch (...) { 3498 *returnedPtr = NULL; 3499 return kOfxStatErrBadHandle; 3500 } 3501 } 3502 imageMemoryUnlock(OfxImageMemoryHandle memoryHandle)3503 static OfxStatus imageMemoryUnlock(OfxImageMemoryHandle memoryHandle){ 3504 try { 3505 Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle); 3506 3507 if(memoryInstance && memoryInstance->verifyMagic()){ 3508 memoryInstance->unlock(); 3509 3510 return kOfxStatOK; 3511 } 3512 3513 return kOfxStatErrBadHandle; 3514 } catch (...) { 3515 return kOfxStatErrBadHandle; 3516 } 3517 } 3518 3519 static const struct OfxImageEffectSuiteV1 gImageEffectSuite = { 3520 getPropertySet, 3521 getParamSet, 3522 clipDefine, 3523 clipGetHandle, 3524 clipGetPropertySet, 3525 clipGetImage, 3526 clipReleaseImage, 3527 clipGetRegionOfDefinition, 3528 abort, 3529 imageMemoryAlloc, 3530 imageMemoryFree, 3531 imageMemoryLock, 3532 imageMemoryUnlock 3533 }; 3534 3535 # ifdef OFX_EXTENSIONS_VEGAS 3536 static const struct OfxVegasStereoscopicImageEffectSuiteV1 gVegasStereoscopicImageEffectSuite = { 3537 clipGetStereoscopicImage 3538 }; 3539 # endif 3540 3541 # ifdef OFX_EXTENSIONS_NUKE 3542 clipGetImagePlane(OfxImageClipHandle clip,OfxTime time,int view,const char * plane,const OfxRectD * region,OfxPropertySetHandle * imageHandle)3543 static OfxStatus clipGetImagePlane(OfxImageClipHandle clip, 3544 OfxTime time, 3545 int view, 3546 const char *plane, 3547 const OfxRectD *region, 3548 OfxPropertySetHandle *imageHandle) 3549 { 3550 try { 3551 if (!imageHandle) { 3552 return kOfxStatErrBadHandle; 3553 } 3554 3555 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip); 3556 if (!clipInstance || !clipInstance->verifyMagic()) { 3557 *imageHandle = NULL; 3558 3559 return kOfxStatErrBadHandle; 3560 } 3561 if ( OFX::IsNaN(time) ) { 3562 *imageHandle = NULL; 3563 3564 return kOfxStatFailed; 3565 } 3566 Image* image = clipInstance->getImagePlane(time, view, plane, region); 3567 if(!image) { 3568 *imageHandle = NULL; 3569 3570 return kOfxStatFailed; 3571 } 3572 3573 *imageHandle = image->getPropHandle(); 3574 3575 return kOfxStatOK; 3576 3577 3578 } catch (...) { 3579 *imageHandle = NULL; 3580 return kOfxStatErrBadHandle; 3581 } 3582 3583 } 3584 clipGetImagePlane(OfxImageClipHandle clip,OfxTime time,const char * plane,const OfxRectD * region,OfxPropertySetHandle * imageHandle)3585 static OfxStatus clipGetImagePlane(OfxImageClipHandle clip, 3586 OfxTime time, 3587 const char *plane, 3588 const OfxRectD *region, 3589 OfxPropertySetHandle *imageHandle) 3590 { 3591 return clipGetImagePlane(clip, time, -1, plane, region, imageHandle); 3592 } 3593 3594 3595 3596 /// get the rod on the given clip at the given time for the given view clipGetRegionOfDefinition(OfxImageClipHandle clip,OfxTime time,int view,OfxRectD * bounds)3597 static OfxStatus clipGetRegionOfDefinition(OfxImageClipHandle clip, 3598 OfxTime time, 3599 int view, 3600 OfxRectD *bounds) 3601 { 3602 try { 3603 if (!bounds) { 3604 return kOfxStatErrBadHandle; 3605 } 3606 3607 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip); 3608 3609 if (!clipInstance || !clipInstance->verifyMagic()) { 3610 bounds->x1 = bounds->y1 = bounds->x2 = bounds->y2 = 0.; 3611 3612 return kOfxStatErrBadHandle; 3613 } 3614 3615 if ( OFX::IsNaN(time) ) { 3616 return kOfxStatFailed; 3617 } 3618 *bounds = clipInstance->getRegionOfDefinition(time, view); 3619 if (bounds->x2 < bounds->x1 || bounds->y2 < bounds->y1) { 3620 // the RoD is invalid (empty is OK) 3621 3622 return kOfxStatFailed; 3623 } 3624 3625 return kOfxStatOK; 3626 } catch (...) { 3627 return kOfxStatErrBadHandle; 3628 } 3629 3630 } 3631 3632 /// get the textual representation of the view getViewName(OfxImageEffectHandle effect,int view,const char ** viewName)3633 static OfxStatus getViewName(OfxImageEffectHandle effect, 3634 int view, 3635 const char **viewName) 3636 { 3637 try { 3638 if (!viewName) { 3639 return kOfxStatErrBadHandle; 3640 } 3641 3642 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(effect); 3643 3644 if (!effectBase || !effectBase->verifyMagic()) { 3645 *viewName = 0; 3646 return kOfxStatErrBadHandle; 3647 } 3648 3649 ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase); 3650 if (!effectInstance) { 3651 *viewName = 0; 3652 return kOfxStatErrBadHandle; 3653 } 3654 3655 effectInstance->getViewName(view, viewName); 3656 return kOfxStatOK; 3657 } catch (...) { 3658 *viewName = 0; 3659 return kOfxStatErrBadHandle; 3660 } 3661 } 3662 3663 /// get the number of views getViewCount(OfxImageEffectHandle effect,int * nViews)3664 static OfxStatus getViewCount(OfxImageEffectHandle effect, 3665 int *nViews) 3666 { 3667 try { 3668 if (!nViews) { 3669 return kOfxStatErrBadHandle; 3670 } 3671 3672 ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(effect); 3673 3674 if (!effectBase || !effectBase->verifyMagic()) { 3675 *nViews = 0; 3676 return kOfxStatErrBadHandle; 3677 } 3678 3679 ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase); 3680 if (!effectInstance) { 3681 *nViews = 0; 3682 return kOfxStatErrBadHandle; 3683 } 3684 3685 effectInstance->getViewCount(nViews); 3686 return kOfxStatOK; 3687 } catch (...) { 3688 *nViews = 0; 3689 return kOfxStatErrBadHandle; 3690 } 3691 } 3692 3693 static const struct FnOfxImageEffectPlaneSuiteV1 gPlaneSuiteV1 = { 3694 clipGetImagePlane 3695 }; 3696 3697 static const struct FnOfxImageEffectPlaneSuiteV2 gPlaneSuiteV2 = { 3698 clipGetImagePlane, 3699 clipGetRegionOfDefinition, 3700 getViewName, 3701 getViewCount 3702 }; 3703 # endif 3704 3705 # ifdef OFX_SUPPORTS_OPENGLRENDER 3706 //////////////////////////////////////////////////////////////////////////////// 3707 //////////////////////////////////////////////////////////////////////////////// 3708 //////////////////////////////////////////////////////////////////////////////// 3709 /// The OpenGL render suite functions 3710 clipLoadTexture(OfxImageClipHandle h1,OfxTime time,const char * format,const OfxRectD * h2,OfxPropertySetHandle * h3)3711 static OfxStatus clipLoadTexture(OfxImageClipHandle h1, 3712 OfxTime time, 3713 const char *format, 3714 const OfxRectD *h2, 3715 OfxPropertySetHandle *h3) 3716 { 3717 try { 3718 if (!h3) { 3719 return kOfxStatErrBadHandle; 3720 } 3721 3722 ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(h1); 3723 3724 if (!clipInstance || !clipInstance->verifyMagic()) { 3725 return kOfxStatErrBadHandle; 3726 } 3727 3728 if(clipInstance){ 3729 if ( OFX::IsNaN(time) ) { 3730 *h3 = NULL; 3731 3732 return kOfxStatFailed; 3733 } 3734 Texture* texture = clipInstance->loadTexture(time,format,h2); 3735 if(!texture) { 3736 *h3 = NULL; 3737 3738 return kOfxStatFailed; 3739 } 3740 3741 *h3 = texture->getPropHandle(); 3742 3743 return kOfxStatOK; 3744 } 3745 3746 return kOfxStatErrBadHandle; 3747 } catch (...) { 3748 *h3 = NULL; 3749 3750 return kOfxStatErrBadHandle; 3751 } 3752 } 3753 clipFreeTexture(OfxPropertySetHandle h1)3754 static OfxStatus clipFreeTexture(OfxPropertySetHandle h1) 3755 { 3756 try { 3757 Property::Set *pset = reinterpret_cast<Property::Set*>(h1); 3758 3759 if (!pset || !pset->verifyMagic()) { 3760 return kOfxStatErrBadHandle; 3761 } 3762 3763 Texture *texture = dynamic_cast<Texture*>(pset); 3764 3765 if(texture){ 3766 // clip::texture has a virtual destructor for derived classes 3767 texture->releaseReference(); 3768 return kOfxStatOK; 3769 } 3770 else 3771 return kOfxStatErrBadHandle; 3772 } catch (...) { 3773 return kOfxStatErrBadHandle; 3774 } 3775 } 3776 flushResources()3777 static OfxStatus flushResources( ) 3778 { 3779 return gImageEffectHost->flushOpenGLResources(); 3780 } 3781 3782 static const struct OfxImageEffectOpenGLRenderSuiteV1 gOpenGLRenderSuite = { 3783 clipLoadTexture, 3784 clipFreeTexture, 3785 flushResources 3786 }; 3787 # endif 3788 3789 /// message suite function for an image effect message(void * handle,const char * type,const char * id,const char * format,...)3790 static OfxStatus message(void *handle, const char *type, const char *id, const char *format, ...) 3791 { 3792 try { 3793 ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle); 3794 OfxStatus stat; 3795 if(effectInstance){ 3796 va_list args; 3797 va_start(args,format); 3798 stat = effectInstance->vmessage(type,id,format,args); 3799 va_end(args); 3800 } 3801 else{ 3802 va_list args; 3803 va_start(args,format); 3804 vprintf(format,args); 3805 va_end(args); 3806 stat = kOfxStatErrBadHandle; 3807 } 3808 return stat; 3809 } catch (...) { 3810 return kOfxStatFailed; 3811 } 3812 } 3813 setPersistentMessage(void * handle,const char * type,const char * id,const char * format,...)3814 static OfxStatus setPersistentMessage(void *handle, const char *type, const char *id, const char *format, ...) 3815 { 3816 try { 3817 ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle); 3818 OfxStatus stat; 3819 if(effectInstance){ 3820 va_list args; 3821 va_start(args,format); 3822 stat = effectInstance->setPersistentMessage(type,id,format,args); 3823 va_end(args); 3824 } 3825 else{ 3826 va_list args; 3827 va_start(args,format); 3828 vprintf(format,args); 3829 va_end(args); 3830 stat = kOfxStatErrBadHandle; 3831 } 3832 return stat; 3833 } catch (...) { 3834 return kOfxStatFailed; 3835 } 3836 } 3837 clearPersistentMessage(void * handle)3838 static OfxStatus clearPersistentMessage(void *handle) 3839 { 3840 try { 3841 ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle); 3842 OfxStatus stat; 3843 if(effectInstance){ 3844 stat = effectInstance->clearPersistentMessage(); 3845 } 3846 else{ 3847 stat = kOfxStatErrBadHandle; 3848 } 3849 return stat; 3850 } catch (...) { 3851 return kOfxStatFailed; 3852 } 3853 } 3854 3855 /// message suite for an image effect plugin (backward-compatible with OfxMessageSuiteV1) 3856 static const struct OfxMessageSuiteV2 gMessageSuite = { 3857 message, 3858 setPersistentMessage, 3859 clearPersistentMessage 3860 }; 3861 3862 #ifdef OFX_SUPPORTS_DIALOG 3863 3864 #ifdef OFX_SUPPORTS_DIALOG_V1 3865 //////////////////////////////////////////////////////////////////////////////// 3866 //////////////////////////////////////////////////////////////////////////////// 3867 // Dialog suite functions requestDialogV1(void * user_data)3868 static OfxStatus requestDialogV1(void *user_data) 3869 { 3870 // In OfxDialogSuiteV1, only the host can figure out which effect instance triggered 3871 // that request. 3872 return gImageEffectHost->requestDialog(NULL, NULL, user_data); 3873 } 3874 notifyredrawPendingV1()3875 static OfxStatus notifyredrawPendingV1() 3876 { 3877 return gImageEffectHost->notifyRedrawPending(NULL, NULL); 3878 } 3879 3880 3881 /// dialog suite for an image effect plugin 3882 static const struct OfxDialogSuiteV1 gDialogSuiteV1 = { 3883 requestDialogV1, 3884 notifyredrawPendingV1 3885 }; 3886 #endif 3887 requestDialog(OfxImageEffectHandle instance,OfxPropertySetHandle inArgs,void * instanceData)3888 static OfxStatus requestDialog(OfxImageEffectHandle instance, OfxPropertySetHandle inArgs, void *instanceData) 3889 { 3890 // In OfxDialogSuiteV1, only the host can figure out which effect instance triggered 3891 // that request. 3892 return gImageEffectHost->requestDialog(instance, inArgs, instanceData); 3893 } 3894 notifyredrawPending(OfxImageEffectHandle instance,OfxPropertySetHandle inArgs)3895 static OfxStatus notifyredrawPending(OfxImageEffectHandle instance, OfxPropertySetHandle inArgs) 3896 { 3897 return gImageEffectHost->notifyRedrawPending(instance, inArgs); 3898 } 3899 3900 /// dialog suite for an image effect plugin 3901 static const struct OfxDialogSuiteV2 gDialogSuiteV2 = { 3902 requestDialog, 3903 notifyredrawPending 3904 }; 3905 #endif // OFX_SUPPORTS_DIALOG 3906 3907 //////////////////////////////////////////////////////////////////////////////// 3908 /// make an overlay interact for an image effect OverlayInteract(ImageEffect::Instance & effect,int bitDepthPerComponent,bool hasAlpha)3909 OverlayInteract::OverlayInteract(ImageEffect::Instance &effect, int bitDepthPerComponent, bool hasAlpha) 3910 : Interact::Instance(effect.getOverlayDescriptor(bitDepthPerComponent, hasAlpha), 3911 (void *)(effect.getHandle())) 3912 , _instance(effect) 3913 { 3914 } 3915 3916 //////////////////////////////////////////////////////////////////////////////// 3917 //////////////////////////////////////////////////////////////////////////////// 3918 // Progress suite functions 3919 3920 /// begin progressing ProgressStartV1(void * effectInstance,const char * label)3921 static OfxStatus ProgressStartV1(void *effectInstance, 3922 const char *label) 3923 { 3924 if (!effectInstance) 3925 return kOfxStatErrBadHandle; 3926 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3927 me->progressStart(label, ""); 3928 return kOfxStatOK; 3929 } 3930 3931 3932 /// begin progressing ProgressStart(void * effectInstance,const char * message,const char * messageid)3933 static OfxStatus ProgressStart(void *effectInstance, 3934 const char *message, 3935 const char *messageid) 3936 { 3937 if (!effectInstance) 3938 return kOfxStatErrBadHandle; 3939 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3940 me->progressStart(message, messageid); 3941 return kOfxStatOK; 3942 } 3943 3944 /// finish progressing ProgressEnd(void * effectInstance)3945 static OfxStatus ProgressEnd(void *effectInstance) 3946 { 3947 if (!effectInstance) 3948 return kOfxStatErrBadHandle; 3949 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3950 me->progressEnd(); 3951 return kOfxStatOK; 3952 } 3953 3954 /// update progressing ProgressUpdate(void * effectInstance,double progress)3955 static OfxStatus ProgressUpdate(void *effectInstance, double progress) 3956 { 3957 if (!effectInstance) 3958 return kOfxStatErrBadHandle; 3959 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3960 bool v = me->progressUpdate(progress); 3961 return v ? kOfxStatOK : kOfxStatReplyNo; 3962 } 3963 3964 /// our progress suite 3965 struct OfxProgressSuiteV1 gProgressSuiteV1 = { 3966 ProgressStartV1, 3967 ProgressUpdate, 3968 ProgressEnd 3969 }; 3970 3971 struct OfxProgressSuiteV2 gProgressSuiteV2 = { 3972 ProgressStart, 3973 ProgressUpdate, 3974 ProgressEnd 3975 }; 3976 3977 3978 //////////////////////////////////////////////////////////////////////////////// 3979 //////////////////////////////////////////////////////////////////////////////// 3980 // timeline suite functions 3981 3982 /// timeline suite function TimeLineGetTime(void * effectInstance,double * time)3983 static OfxStatus TimeLineGetTime(void *effectInstance, double *time) 3984 { 3985 if (!effectInstance) 3986 return kOfxStatErrBadHandle; 3987 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3988 *time = me->timeLineGetTime(); 3989 return kOfxStatOK; 3990 } 3991 3992 /// timeline suite function TimeLineGotoTime(void * effectInstance,double time)3993 static OfxStatus TimeLineGotoTime(void *effectInstance, double time) 3994 { 3995 if (!effectInstance) 3996 return kOfxStatErrBadHandle; 3997 Instance *me = reinterpret_cast<Instance *>(effectInstance); 3998 me->timeLineGotoTime(time); 3999 return kOfxStatOK; 4000 } 4001 4002 /// timeline suite function TimeLineGetBounds(void * effectInstance,double * firstTime,double * lastTime)4003 static OfxStatus TimeLineGetBounds(void *effectInstance, double *firstTime, double *lastTime) 4004 { 4005 if (!effectInstance) 4006 return kOfxStatErrBadHandle; 4007 Instance *me = reinterpret_cast<Instance *>(effectInstance); 4008 me->timeLineGetBounds(*firstTime, *lastTime); 4009 return kOfxStatOK; 4010 } 4011 4012 /// our progress suite 4013 struct OfxTimeLineSuiteV1 gTimelineSuite = { 4014 TimeLineGetTime, 4015 TimeLineGotoTime, 4016 TimeLineGetBounds 4017 }; 4018 4019 //////////////////////////////////////////////////////////////////////////////// 4020 #ifdef OFX_SUPPORTS_MULTITHREAD 4021 // Forward all multithread suite calls to the host implementation. 4022 multiThread(OfxThreadFunctionV1 func,unsigned int nThreads,void * customArg)4023 static OfxStatus multiThread(OfxThreadFunctionV1 func, 4024 unsigned int nThreads, 4025 void *customArg) 4026 { 4027 return gImageEffectHost->multiThread(func, nThreads, customArg); 4028 } 4029 multiThreadNumCPUs(unsigned int * nCPUs)4030 static OfxStatus multiThreadNumCPUs(unsigned int *nCPUs) 4031 { 4032 return gImageEffectHost->multiThreadNumCPUS(nCPUs); 4033 } 4034 multiThreadIndex(unsigned int * threadIndex)4035 static OfxStatus multiThreadIndex(unsigned int *threadIndex){ 4036 return gImageEffectHost->multiThreadIndex(threadIndex); 4037 } 4038 multiThreadIsSpawnedThread(void)4039 static int multiThreadIsSpawnedThread(void){ 4040 return gImageEffectHost->multiThreadIsSpawnedThread(); 4041 } 4042 mutexCreate(OfxMutexHandle * mutex,int lockCount)4043 static OfxStatus mutexCreate(OfxMutexHandle *mutex, int lockCount) 4044 { 4045 return gImageEffectHost->mutexCreate(mutex, lockCount); 4046 } 4047 mutexDestroy(const OfxMutexHandle mutex)4048 static OfxStatus mutexDestroy(const OfxMutexHandle mutex) 4049 { 4050 return gImageEffectHost->mutexDestroy(mutex); 4051 } 4052 mutexLock(const OfxMutexHandle mutex)4053 static OfxStatus mutexLock(const OfxMutexHandle mutex){ 4054 return gImageEffectHost->mutexLock(mutex); 4055 } 4056 mutexUnLock(const OfxMutexHandle mutex)4057 static OfxStatus mutexUnLock(const OfxMutexHandle mutex){ 4058 return gImageEffectHost->mutexUnLock(mutex); 4059 } 4060 mutexTryLock(const OfxMutexHandle mutex)4061 static OfxStatus mutexTryLock(const OfxMutexHandle mutex){ 4062 return gImageEffectHost->mutexTryLock(mutex); 4063 } 4064 #else // !OFX_SUPPORTS_MULTITHREAD 4065 /// a simple multithread suite multiThread(OfxThreadFunctionV1 func,unsigned int,void * customArg)4066 static OfxStatus multiThread(OfxThreadFunctionV1 func, 4067 unsigned int /*nThreads*/, 4068 void *customArg) 4069 { 4070 if (!func) 4071 return kOfxStatFailed; 4072 func(0,1,customArg); 4073 return kOfxStatOK; 4074 } 4075 multiThreadNumCPUs(unsigned int * nCPUs)4076 static OfxStatus multiThreadNumCPUs(unsigned int *nCPUs) 4077 { 4078 if (!nCPUs) 4079 return kOfxStatFailed; 4080 *nCPUs = 1; 4081 return kOfxStatOK; 4082 } 4083 multiThreadIndex(unsigned int * threadIndex)4084 static OfxStatus multiThreadIndex(unsigned int *threadIndex){ 4085 if (!threadIndex) 4086 return kOfxStatFailed; 4087 *threadIndex = 0; 4088 return kOfxStatOK; 4089 } 4090 multiThreadIsSpawnedThread(void)4091 static int multiThreadIsSpawnedThread(void){ 4092 return false; 4093 } 4094 mutexCreate(OfxMutexHandle * mutex,int)4095 static OfxStatus mutexCreate(OfxMutexHandle *mutex, int /*lockCount*/) 4096 { 4097 if (!mutex) 4098 return kOfxStatFailed; 4099 // do nothing single threaded 4100 *mutex = 0; 4101 return kOfxStatOK; 4102 } 4103 mutexDestroy(const OfxMutexHandle mutex)4104 static OfxStatus mutexDestroy(const OfxMutexHandle mutex) 4105 { 4106 if (mutex != 0) 4107 return kOfxStatErrBadHandle; 4108 // do nothing single threaded 4109 return kOfxStatOK; 4110 } 4111 mutexLock(const OfxMutexHandle mutex)4112 static OfxStatus mutexLock(const OfxMutexHandle mutex){ 4113 if (mutex != 0) 4114 return kOfxStatErrBadHandle; 4115 // do nothing single threaded 4116 return kOfxStatOK; 4117 } 4118 mutexUnLock(const OfxMutexHandle mutex)4119 static OfxStatus mutexUnLock(const OfxMutexHandle mutex){ 4120 if (mutex != 0) 4121 return kOfxStatErrBadHandle; 4122 // do nothing single threaded 4123 return kOfxStatOK; 4124 } 4125 mutexTryLock(const OfxMutexHandle mutex)4126 static OfxStatus mutexTryLock(const OfxMutexHandle mutex){ 4127 if (mutex != 0) 4128 return kOfxStatErrBadHandle; 4129 // do nothing single threaded 4130 return kOfxStatOK; 4131 } 4132 #endif // !OFX_SUPPORTS_MULTITHREAD 4133 4134 static const struct OfxMultiThreadSuiteV1 gMultiThreadSuite = { 4135 multiThread, 4136 multiThreadNumCPUs, 4137 multiThreadIndex, 4138 multiThreadIsSpawnedThread, 4139 mutexCreate, 4140 mutexDestroy, 4141 mutexLock, 4142 mutexUnLock, 4143 mutexTryLock 4144 }; 4145 4146 4147 //////////////////////////////////////////////////////////////////////////////// 4148 /// The image effect host 4149 4150 /// properties for the image effect host 4151 static const Property::PropSpec hostStuffs[] = { 4152 { kOfxImageEffectHostPropIsBackground, Property::eInt, 1, true, "0" }, 4153 { kOfxImageEffectPropSupportsOverlays, Property::eInt, 1, true, "1" }, 4154 { kOfxImageEffectPropSupportsMultiResolution, Property::eInt, 1, true, "1" }, 4155 { kOfxImageEffectPropSupportsTiles, Property::eInt, 1, true, "1" }, 4156 { kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, true, "1" }, 4157 4158 4159 4160 /// xxx this needs defaulting manually 4161 { kOfxImageEffectPropSupportedComponents, Property::eString, 0, true, "" }, 4162 /// xxx this needs defaulting manually 4163 4164 { kOfxImageEffectPropSupportedPixelDepths, Property::eString, 0, true, "" }, 4165 4166 /// xxx this needs defaulting manually 4167 4168 { kOfxImageEffectPropSupportedContexts, Property::eString, 0, true, "" }, 4169 /// xxx this needs defaulting manually 4170 4171 { kOfxImageEffectPropSupportsMultipleClipDepths, Property::eInt, 1, true, "1" }, 4172 { kOfxImageEffectPropSupportsMultipleClipPARs, Property::eInt, 1, true, "0" }, 4173 { kOfxImageEffectPropSetableFrameRate, Property::eInt, 1, true, "0" }, 4174 { kOfxImageEffectPropSetableFielding, Property::eInt, 1, true, "0" }, 4175 { kOfxParamHostPropSupportsCustomInteract, Property::eInt, 1, true, "0" }, 4176 { kOfxParamHostPropSupportsStringAnimation, Property::eInt, 1, true, "0" }, 4177 { kOfxParamHostPropSupportsChoiceAnimation, Property::eInt, 1, true, "0" }, 4178 # ifdef OFX_EXTENSIONS_RESOLVE 4179 { kOfxParamHostPropSupportsStrChoiceAnimation, Property::eInt, 1, true, "0" }, 4180 # endif 4181 { kOfxParamHostPropSupportsBooleanAnimation, Property::eInt, 1, true, "0" }, 4182 { kOfxParamHostPropSupportsCustomAnimation, Property::eInt, 1, true, "0" }, 4183 { kOfxPropHostOSHandle, Property::ePointer, 1, true, NULL }, 4184 # ifdef OFX_SUPPORTS_PARAMETRIC 4185 { kOfxParamHostPropSupportsParametricAnimation, Property::eInt, 1, true, "0"}, 4186 # ifdef OFX_SUPPORTS_PARAMETRIC_V2 4187 { kOfxHostPropSupportedParametricInterpolations, Property::eString, 0, true, ""}, 4188 # endif 4189 # endif 4190 { kOfxParamHostPropMaxParameters, Property::eInt, 1, true, "-1" }, 4191 { kOfxParamHostPropMaxPages, Property::eInt, 1, true, "0" }, 4192 { kOfxParamHostPropPageRowColumnCount, Property::eInt, 2, true, "0" }, 4193 { kOfxImageEffectInstancePropSequentialRender, Property::eInt, 1, true, "0" }, // OFX 1.2 4194 # ifdef OFX_SUPPORTS_OPENGLRENDER 4195 { kOfxImageEffectPropOpenGLRenderSupported, Property::eString, 1, true, "false"}, // OFX 1.3 4196 # endif 4197 { kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, // OFX 1.4 4198 { kOfxImageEffectHostPropNativeOrigin, Property::eString, 0, true, kOfxHostNativeOriginBottomLeft }, // OFX 1.4 4199 # ifdef OFX_EXTENSIONS_RESOLVE 4200 { kOfxImageEffectPropOpenCLRenderSupported, Property::eString, 1, false, "false"}, 4201 { kOfxImageEffectPropCudaRenderSupported, Property::eString, 1, false, "false" }, 4202 # endif 4203 # ifdef OFX_EXTENSIONS_NUKE 4204 { kFnOfxImageEffectPropMultiPlanar, Property::eInt, 1, false, "0" }, 4205 { kFnOfxImageEffectCanTransform, Property::eInt, 1, true, "0" }, 4206 # endif 4207 # ifdef OFX_EXTENSIONS_NATRON 4208 { kNatronOfxHostIsNatron, Property::eInt, 1, true, "0" }, 4209 { kNatronOfxParamHostPropSupportsDynamicChoices, Property::eInt, 1, true, "0" }, 4210 { kNatronOfxParamPropChoiceCascading, Property::eInt, 1, true, "0" }, 4211 { kNatronOfxImageEffectPropChannelSelector, Property::eString, 1, true, kOfxImageComponentNone }, 4212 { kNatronOfxImageEffectPropHostMasking, Property::eInt, 1, true, "0" }, 4213 { kNatronOfxImageEffectPropHostMixing, Property::eInt, 1, true, "0" }, 4214 { kNatronOfxPropDescriptionIsMarkdown, Property::eInt, 1, true, "0" }, 4215 { kNatronOfxImageEffectPropDefaultCursors, Property::eString, 0, true, "" }, 4216 { kNatronOfxPropNativeOverlays, Property::eString, 0, true, ""}, 4217 { kOfxImageEffectPropCanDistort, Property::eInt, 1, false, "0" }, 4218 # endif 4219 Property::propSpecEnd 4220 }; 4221 4222 /// ctor Host()4223 Host::Host() 4224 { 4225 /// add the properties for an image effect host, derived classs to set most of them 4226 _properties.addProperties(hostStuffs); 4227 } 4228 4229 /// optionally over-ridden function to register the creation of a new descriptor in the host app initDescriptor(Descriptor *)4230 void Host::initDescriptor(Descriptor* /*desc*/) 4231 { 4232 } 4233 4234 /// Use this in any dialogue etc... showing progress loadingStatus(bool,const std::string &,int,int)4235 void Host::loadingStatus(bool /*loading*/, const std::string &/*id*/, int /*versionMajor*/, int /*versionMinor*/) 4236 { 4237 } 4238 pluginSupported(ImageEffectPlugin *,std::string &) const4239 bool Host::pluginSupported(ImageEffectPlugin */*plugin*/, std::string &/*reason*/) const 4240 { 4241 return true; 4242 } 4243 4244 // override this to use your own memory instance - must inherrit from memory::instance newMemoryInstance(size_t)4245 Memory::Instance* Host::newMemoryInstance(size_t /*nBytes*/) { 4246 return 0; 4247 } 4248 4249 // return an memory::instance calls makeMemoryInstance that can be overriden imageMemoryAlloc(size_t nBytes)4250 Memory::Instance* Host::imageMemoryAlloc(size_t nBytes){ 4251 Memory::Instance* instance = newMemoryInstance(nBytes); 4252 if(instance) 4253 return instance; 4254 else{ 4255 Memory::Instance* instance = new Memory::Instance; 4256 instance->alloc(nBytes); 4257 return instance; 4258 } 4259 } 4260 4261 /// our suite fetcher fetchSuite(const char * suiteName,int suiteVersion)4262 const void *Host::fetchSuite(const char *suiteName, int suiteVersion) 4263 { 4264 if (strcmp(suiteName, kOfxImageEffectSuite)==0) { 4265 if(suiteVersion==1) 4266 return (void *)&gImageEffectSuite; 4267 else 4268 return NULL; 4269 } 4270 else if (strcmp(suiteName, kOfxParameterSuite)==0) { 4271 return Param::GetSuite(suiteVersion); 4272 } 4273 else if (strcmp(suiteName, kOfxMessageSuite)==0) { 4274 // version 2 is backward-compatible 4275 if(suiteVersion==1 || suiteVersion==2) 4276 return (void *)&gMessageSuite; 4277 else 4278 return NULL; 4279 } 4280 #ifdef OFX_SUPPORTS_DIALOG 4281 else if (strcmp(suiteName, kOfxDialogSuite)==0) { 4282 if(suiteVersion==1) 4283 #ifdef OFX_SUPPORTS_DIALOG_V1 4284 return (void *)&gDialogSuiteV1; 4285 #else 4286 return (void *)0; 4287 #endif 4288 else if(suiteVersion==2) 4289 return (void *)&gDialogSuiteV2; 4290 else 4291 return NULL; 4292 } 4293 #endif 4294 else if (strcmp(suiteName, kOfxInteractSuite)==0) { 4295 return Interact::GetSuite(suiteVersion); 4296 } 4297 else if (strcmp(suiteName, kOfxProgressSuite)==0) { 4298 if(suiteVersion==1) 4299 return (void*)&gProgressSuiteV1; 4300 else if(suiteVersion==2) 4301 return (void*)&gProgressSuiteV2; 4302 else 4303 return 0; 4304 } 4305 # ifdef OFX_EXTENSIONS_VEGAS 4306 else if (strcmp(suiteName, kOfxVegasProgressSuite)==0) { 4307 if(suiteVersion == 1) 4308 return (void*)&gProgressSuiteV2; 4309 //if(suiteVersion == 2) 4310 // return (void*)&gVegasProgressSuiteV2; 4311 else 4312 return NULL; 4313 } 4314 # endif 4315 else if (strcmp(suiteName, kOfxTimeLineSuite)==0) { 4316 if(suiteVersion==1) 4317 return (void*)&gTimelineSuite; 4318 else 4319 return 0; 4320 } 4321 else if (strcmp(suiteName, kOfxMultiThreadSuite)==0) { 4322 if(suiteVersion == 1) 4323 return (void*)&gMultiThreadSuite; 4324 else 4325 return NULL; 4326 } 4327 # ifdef OFX_SUPPORTS_OPENGLRENDER 4328 else if (strcmp(suiteName, kOfxOpenGLRenderSuite)==0) { 4329 if(suiteVersion == 1) 4330 return (void*)&gOpenGLRenderSuite; 4331 else 4332 return NULL; 4333 } 4334 # endif 4335 # ifdef OFX_EXTENSIONS_VEGAS 4336 # if 0 4337 else if (strcmp(suiteName, kOfxVegasKeyframeSuite)==0) { 4338 if(suiteVersion == 1) 4339 return (void*)&gVegasKeyframeSuite; 4340 else 4341 return NULL; 4342 } 4343 # endif 4344 else if (strcmp(suiteName, kOfxVegasStereoscopicImageEffectSuite)==0) { 4345 if(suiteVersion == 1) 4346 return (void*)&gVegasStereoscopicImageEffectSuite; 4347 else 4348 return NULL; 4349 } 4350 # endif 4351 # ifdef OFX_SUPPORTS_PARAMETRIC 4352 else if (strcmp(suiteName, kOfxParametricParameterSuite)==0) { 4353 return ParametricParam::GetSuite(suiteVersion); 4354 } 4355 # endif 4356 # ifdef OFX_EXTENSIONS_NUKE 4357 else if (strcmp(suiteName,kFnOfxImageEffectPlaneSuite) == 0 && suiteVersion == 1) { 4358 return (void*)&gPlaneSuiteV1; 4359 } 4360 else if (strcmp(suiteName,kFnOfxImageEffectPlaneSuite) == 0 && suiteVersion == 2) { 4361 return (void*)&gPlaneSuiteV2; 4362 } 4363 # endif 4364 else /// otherwise just grab the base class one, which is props and memory 4365 return OFX::Host::Host::fetchSuite(suiteName, suiteVersion); 4366 } 4367 4368 } // ImageEffect 4369 4370 } // Host 4371 4372 } // OFX 4373