#include <math.h>
#include "ofxCore.h"
#include "ofxImageEffect.h"
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhImageEffect.h"
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include "ofxhHost.h"
#include "ofxhImageEffectAPI.h"
#include "ofxhUtilities.h"
#ifdef OFX_SUPPORTS_PARAMETRIC
#include "ofxhParametricParam.h"
#endif
#ifdef OFX_SUPPORTS_OPENGLRENDER
#include "ofxOpenGLRender.h"
#endif
#include "ofxOld.h"
#include <string.h>
#include <stdarg.h>
namespace OFX {
namespace Host {
namespace ImageEffect {
static const Property::PropSpec effectDescriptorStuff[] = {
{ kOfxPropType, Property::eString, 1, true, kOfxTypeImageEffect },
{ kOfxPropLabel, Property::eString, 1, false, "" },
{ kOfxPropShortLabel, Property::eString, 1, false, "" },
{ kOfxPropLongLabel, Property::eString, 1, false, "" },
{ kOfxPropVersion, Property::eInt, 0, false, "0" },
{ kOfxPropVersionLabel, Property::eString, 1, false, "" },
{ kOfxPropPluginDescription, Property::eString, 1, false, "" },
{ kOfxImageEffectPropSupportedContexts, Property::eString, 0, false, "" },
{ kOfxImageEffectPluginPropGrouping, Property::eString, 1, false, "" },
{ kOfxImageEffectPluginPropSingleInstance, Property::eInt, 1, false, "0" },
{ kOfxImageEffectPluginRenderThreadSafety, Property::eString, 1, false, kOfxImageEffectRenderInstanceSafe },
{ kOfxImageEffectPluginPropHostFrameThreading, Property::eInt, 1, false, "1" },
{ kOfxImageEffectPluginPropOverlayInteractV1, Property::ePointer, 1, false, NULL },
{ kOfxImageEffectPropSupportsMultiResolution, Property::eInt, 1, false, "1" } ,
{ kOfxImageEffectPropSupportsTiles, Property::eInt, 1, false, "1" },
{ kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, false, "0" },
{ kOfxImageEffectPropSupportedPixelDepths, Property::eString, 0, false, "" },
{ kOfxImageEffectPluginPropFieldRenderTwiceAlways, Property::eInt, 1, false, "1" } ,
{ kOfxImageEffectPropSupportsMultipleClipDepths, Property::eInt, 1, false, "0" },
{ kOfxImageEffectPropSupportsMultipleClipPARs, Property::eInt, 1, false, "0" },
{ kOfxImageEffectPropClipPreferencesSlaveParam, Property::eString, 0, false, "" },
{ kOfxImageEffectInstancePropSequentialRender, Property::eInt, 1, false, "0" },
{ kOfxPluginPropFilePath, Property::eString, 1, true, ""},
#ifdef OFX_SUPPORTS_OPENGLRENDER
{ kOfxImageEffectPropOpenGLRenderSupported, Property::eString, 1, false, "false"}, #endif
{ kOfxImageEffectPropCudaRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropCudaStreamSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropMetalRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropOpenCLRenderSupported, Property::eString, 1, false, "false" },
Property::propSpecEnd
};
Base::Base(const Property::Set &set)
: _properties(set)
{}
Base::Base(const Property::PropSpec * propSpec)
: _properties(propSpec)
{}
Base::~Base() {}
OfxImageEffectHandle Base::getHandle() const {
return (OfxImageEffectHandle)this;
}
Property::Set &Base::getProps() {
return _properties;
}
const Property::Set &Base::getProps() const {
return _properties;
}
const std::string &Base::getShortLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropShortLabel);
if(s == "") {
const std::string &s2 = _properties.getStringProperty(kOfxPropLabel);
if(s2 == "") {
return _properties.getStringProperty(kOfxPropName);
}
}
return s;
}
const std::string &Base::getLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropLabel);
if(s == "") {
return _properties.getStringProperty(kOfxPropName);
}
return s;
}
const std::string &Base::getLongLabel() const
{
const std::string &s = _properties.getStringProperty(kOfxPropLongLabel);
if(s == "") {
const std::string &s2 = _properties.getStringProperty(kOfxPropLabel);
if(s2 == "") {
return _properties.getStringProperty(kOfxPropName);
}
}
return s;
}
bool Base::isContextSupported(const std::string &s) const
{
return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedContexts, s) != -1;
}
const std::string &Base::getPluginGrouping() const
{
return _properties.getStringProperty(kOfxImageEffectPluginPropGrouping);
}
bool Base::isSingleInstance() const
{
return _properties.getIntProperty(kOfxImageEffectPluginPropSingleInstance) != 0;
}
const std::string &Base::getRenderThreadSafety() const
{
return _properties.getStringProperty(kOfxImageEffectPluginRenderThreadSafety);
}
bool Base::getHostFrameThreading() const
{
return _properties.getIntProperty(kOfxImageEffectPluginPropHostFrameThreading) != 0;
}
OfxPluginEntryPoint *Base::getOverlayInteractMainEntry() const
{
return (OfxPluginEntryPoint *)(_properties.getPointerProperty(kOfxImageEffectPluginPropOverlayInteractV1));
}
bool Base::supportsMultiResolution() const
{
return _properties.getIntProperty(kOfxImageEffectPropSupportsMultiResolution) != 0;
}
bool Base::supportsTiles() const
{
return _properties.getIntProperty(kOfxImageEffectPropSupportsTiles) != 0;
}
bool Base::temporalAccess() const
{
return _properties.getIntProperty(kOfxImageEffectPropTemporalClipAccess) != 0;
}
bool Base::isPixelDepthSupported(const std::string &s) const
{
return _properties.findStringPropValueIndex(kOfxImageEffectPropSupportedPixelDepths, s) != -1;
}
bool Base::fieldRenderTwiceAlways() const
{
return _properties.getIntProperty(kOfxImageEffectPluginPropFieldRenderTwiceAlways) != 0;
}
bool Base::supportsMultipleClipDepths() const
{
return _properties.getIntProperty(kOfxImageEffectPropSupportsMultipleClipDepths) != 0;
}
bool Base::supportsMultipleClipPARs() const
{
return _properties.getIntProperty(kOfxImageEffectPropSupportsMultipleClipPARs) != 0;
}
bool Base::isClipPreferencesSlaveParam(const std::string &s) const
{
return _properties.findStringPropValueIndex(kOfxImageEffectPropClipPreferencesSlaveParam, s) != -1;
}
Descriptor::Descriptor(Plugin *plug)
: Base(effectDescriptorStuff)
, _plugin(plug)
{
_properties.setStringProperty(kOfxPluginPropFilePath, plug->getBinary()->getBundlePath());
gImageEffectHost->initDescriptor(this);
}
Descriptor::Descriptor(const Descriptor &other, Plugin *plug)
: Base(other._properties)
, _plugin(plug)
{
_properties.setStringProperty(kOfxPluginPropFilePath, plug->getBinary()->getBundlePath());
gImageEffectHost->initDescriptor(this);
}
Descriptor::Descriptor(const std::string &bundlePath, Plugin *plug)
: Base(effectDescriptorStuff)
, _plugin(plug)
{
_properties.setStringProperty(kOfxPluginPropFilePath, bundlePath);
gImageEffectHost->initDescriptor(this);
}
Descriptor::~Descriptor()
{
for(std::map<std::string, ClipDescriptor*>::iterator it = _clips.begin(); it != _clips.end(); ++it)
delete it->second;
_clips.clear();
}
ClipDescriptor *Descriptor::defineClip(const std::string &name) {
ClipDescriptor *c = new ClipDescriptor(name);
_clips[name] = c;
_clipsByOrder.push_back(c);
return c;
}
Property::Set &Descriptor::getParamSetProps()
{
return _properties;
}
Interact::Descriptor &Descriptor::getOverlayDescriptor(int bitDepthPerComponent, bool hasAlpha)
{
if(_overlayDescriptor.getState() == Interact::eUninitialised) {
_overlayDescriptor.setEntryPoint(getOverlayInteractMainEntry());
_overlayDescriptor.describe(bitDepthPerComponent, hasAlpha);
}
return _overlayDescriptor;
}
const std::map<std::string, ClipDescriptor*> &Descriptor::getClips() const {
return _clips;
}
void Descriptor::addClip(const std::string &name, ClipDescriptor *clip) {
_clips[name] = clip;
_clipsByOrder.push_back(clip);
}
static const Property::PropSpec effectInstanceStuff[] = {
{ kOfxPropType, Property::eString, 1, true, kOfxTypeImageEffectInstance },
{ kOfxImageEffectPropContext, Property::eString, 1, true, "" },
{ kOfxPropInstanceData, Property::ePointer, 1, false, NULL },
{ kOfxImageEffectPropPluginHandle, Property::ePointer, 1, false, NULL },
{ kOfxImageEffectPropProjectSize, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropProjectOffset, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropProjectExtent, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropProjectPixelAspectRatio, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectInstancePropEffectDuration, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectInstancePropSequentialRender, Property::eInt, 1, false, "0" },
{ kOfxImageEffectPropFrameRate , Property::eDouble, 1, true, "0" },
{ kOfxPropIsInteractive, Property::eInt, 1, true, "0" },
# ifdef kOfxImageEffectPropInAnalysis
{ kOfxImageEffectPropInAnalysis, Property::eInt, 1, false, "0" }, # endif
{ kOfxImageEffectPropSupportsTiles, Property::eInt, 1, false, "1" }, #ifdef OFX_SUPPORTS_OPENGLRENDER
{ kOfxImageEffectPropOpenGLRenderSupported, Property::eString, 1, false, "false"}, #endif
{ kOfxImageEffectPropCudaRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropCudaStreamSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropMetalRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropOpenCLRenderSupported, Property::eString, 1, false, "false" },
Property::propSpecEnd
};
Instance::Instance(ImageEffectPlugin* plugin,
Descriptor &other,
const std::string &context,
bool interactive)
: Base(effectInstanceStuff)
, _plugin(plugin)
, _context(context)
, _descriptor(&other)
, _interactive(interactive)
, _created(false)
, _clipPrefsDirty(true)
, _continuousSamples(false)
, _frameVarying(false)
, _outputFrameRate(24)
{
int i = 0;
_properties.setChainedSet(&other.getProps());
_properties.setPointerProperty(kOfxImageEffectPropPluginHandle, _plugin->getPluginHandle()->getOfxPlugin());
_properties.setStringProperty(kOfxImageEffectPropContext,context);
_properties.setIntProperty(kOfxPropIsInteractive,interactive);
bool sequential = other.getProps().getIntProperty(kOfxImageEffectInstancePropSequentialRender) != 0;
_properties.setIntProperty(kOfxImageEffectInstancePropSequentialRender,sequential);
while(effectInstanceStuff[i].name) {
if(strcmp(effectInstanceStuff[i].name,kOfxImageEffectPropContext) &&
strcmp(effectInstanceStuff[i].name,kOfxPropIsInteractive) &&
strcmp(effectInstanceStuff[i].name,kOfxImageEffectInstancePropSequentialRender) )
{
const Property::PropSpec& spec = effectInstanceStuff[i];
switch (spec.type) {
case Property::eDouble:
_properties.setGetHook(spec.name, this);
break;
default:
break;
}
}
i++;
}
}
Property::Set &Instance::getParamSetProps()
{
return _properties;
}
OfxStatus Instance::populate()
{
const std::vector<ClipDescriptor*>& clips = _descriptor->getClipsByOrder();
int counter = 0;
for(std::vector<ClipDescriptor*>::const_iterator it=clips.begin();
it!=clips.end();
++it, ++counter) {
const std::string &name = (*it)->getName();
ClipInstance* instance = newClipInstance(this, *it, counter);
if(!instance) return kOfxStatFailed;
_clips[name] = instance;
}
const std::list<Param::Descriptor*>& map = _descriptor->getParamList();
std::map<std::string,std::vector<Param::Instance*> > parameters;
std::map<std::string, Param::Instance*> groups;
for(std::list<Param::Descriptor*>::const_iterator it=map.begin();
it!=map.end();
++it) {
Param::Descriptor* descriptor = (*it);
if(!descriptor) return kOfxStatErrValue;
std::string name = descriptor->getName();
Param::Instance* instance = newParam(name,*descriptor);
if(!instance) return kOfxStatFailed;
OfxStatus st = addParam(name,instance);
if(st != kOfxStatOK) return st;
std::string parent = instance->getParentName();
if(parent!="")
parameters[parent].push_back(instance);
if(instance->getType()==kOfxParamTypeGroup){
groups[instance->getName()]=instance;
}
}
for(std::map<std::string, Param::Instance*>::iterator it=groups.begin();
it!=groups.end();
++it) {
Param::GroupInstance* group = dynamic_cast<Param::GroupInstance*>(it->second);
if(group){
std::map<std::string,std::vector<Param::Instance*> >::iterator it2 = parameters.find(group->getName());
if(it2!=parameters.end()){
group->setChildren(it2->second);
}
}
}
return kOfxStatOK;
}
int Instance::getDimension(const std::string &name) const OFX_EXCEPTION_SPEC {
printf("failing in %s with name=%s\n", __PRETTY_FUNCTION__, name.c_str());
throw Property::Exception(kOfxStatErrMissingHostFeature);
}
int Instance::upperGetDimension(const std::string &name) {
return _properties.getDimension(name);
}
void Instance::notify(const std::string &, bool , int ) OFX_EXCEPTION_SPEC
{
printf("failing in %s\n", __PRETTY_FUNCTION__);
}
void Instance::reset(const std::string &) OFX_EXCEPTION_SPEC {
printf("failing in %s\n", __PRETTY_FUNCTION__);
throw Property::Exception(kOfxStatErrMissingHostFeature);
}
double Instance::getDoubleProperty(const std::string &name, int index) const OFX_EXCEPTION_SPEC
{
if(name==kOfxImageEffectPropProjectSize){
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
double values[2];
getProjectSize(values[0],values[1]);
return values[index];
}
else if(name==kOfxImageEffectPropProjectOffset){
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
double values[2];
getProjectOffset(values[0],values[1]);
return values[index];
}
else if(name==kOfxImageEffectPropProjectExtent){
if(index>=2) throw Property::Exception(kOfxStatErrBadIndex);
double values[2];
getProjectExtent(values[0],values[1]);
return values[index];
}
else if(name==kOfxImageEffectPropProjectPixelAspectRatio){
if(index>=1) throw Property::Exception(kOfxStatErrBadIndex);
return getProjectPixelAspectRatio();
}
else if(name==kOfxImageEffectInstancePropEffectDuration){
if(index>=1) throw Property::Exception(kOfxStatErrBadIndex);
return getEffectDuration();
}
else if(name==kOfxImageEffectPropFrameRate){
if(index>=1) throw Property::Exception(kOfxStatErrBadIndex);
return getFrameRate();
}
else
throw Property::Exception(kOfxStatErrUnknown);
}
void Instance::getDoublePropertyN(const std::string &name, double* first, int n) const OFX_EXCEPTION_SPEC
{
if(name==kOfxImageEffectPropProjectSize){
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
getProjectSize(first[0],first[1]);
}
else if(name==kOfxImageEffectPropProjectOffset){
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
getProjectOffset(first[0],first[1]);
}
else if(name==kOfxImageEffectPropProjectExtent){
if(n>2) throw Property::Exception(kOfxStatErrBadIndex);
getProjectExtent(first[0],first[1]);
}
else if(name==kOfxImageEffectPropProjectPixelAspectRatio){
if(n>1) throw Property::Exception(kOfxStatErrBadIndex);
*first = getProjectPixelAspectRatio();
}
else if(name==kOfxImageEffectInstancePropEffectDuration){
if(n>1) throw Property::Exception(kOfxStatErrBadIndex);
*first = getEffectDuration();
}
else if(name==kOfxImageEffectPropFrameRate){
if(n>1) throw Property::Exception(kOfxStatErrBadIndex);
*first = getFrameRate();
}
else
throw Property::Exception(kOfxStatErrUnknown);
}
Instance::~Instance(){
if (_created) {
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionDestroyInstance<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionDestroyInstance,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionDestroyInstance<<"()->"<<StatStr(st)<<std::endl;
# endif
(void)st;
}
std::map<std::string, ClipInstance*>::iterator i;
for(i = _clips.begin(); i != _clips.end(); ++i) {
if(i->second)
delete i->second;
i->second = NULL;
}
}
void Instance::setCustomInArgs(const std::string &, Property::Set &)
{
}
void Instance::setCustomOutArgs(const std::string &, Property::Set &)
{
}
void Instance::examineOutArgs(const std::string &, OfxStatus, const Property::Set &)
{
}
bool Instance::checkClipConnectionStatus() const
{
std::map<std::string, ClipInstance*>::const_iterator i;
for(i = _clips.begin(); i != _clips.end(); ++i) {
if(!i->second->isOptional() && !i->second->getConnected()) {
return false;
}
}
return true;
}
int Instance::abort() {
return 0;
}
Memory::Instance* Instance::newMemoryInstance(size_t ) {
return 0;
}
Memory::Instance* Instance::imageMemoryAlloc(size_t nBytes){
Memory::Instance* instance = newMemoryInstance(nBytes);
if(instance)
return instance;
else{
Memory::Instance* instance = new Memory::Instance;
instance->alloc(nBytes);
return instance;
}
}
OfxStatus Instance::mainEntry(const char *action,
const void *handle,
Property::Set *inArgs,
Property::Set *outArgs)
{
if(_plugin){
PluginHandle* pHandle = _plugin->getPluginHandle();
if(pHandle){
OfxPlugin* ofxPlugin = pHandle->getOfxPlugin();
if(ofxPlugin){
OfxPropertySetHandle inHandle = 0;
if(inArgs) {
setCustomInArgs(action, *inArgs);
inHandle = inArgs->getHandle();
}
OfxPropertySetHandle outHandle = 0;
if(outArgs) {
setCustomOutArgs(action, *outArgs);
outHandle = outArgs->getHandle();
}
OfxStatus stat;
try {
stat = ofxPlugin->mainEntry(action, handle, inHandle, outHandle);
} CatchAllSetStatus(stat, gImageEffectHost, ofxPlugin, action);
if(outArgs)
examineOutArgs(action, stat, *outArgs);
return stat;
}
return kOfxStatFailed;
}
return kOfxStatFailed;
}
return kOfxStatFailed;
}
ClipInstance* Instance::getNthClip(int index)
{
const std::string name = _descriptor->getClipsByOrder()[index]->getName();
return _clips[name];
}
ClipInstance* Instance::getClip(const std::string& name) const {
std::map<std::string,ClipInstance*>::const_iterator it = _clips.find(name);
if(it!=_clips.end()){
return it->second;
}
return 0;
}
OfxStatus Instance::createInstanceAction()
{
setDefaultClipPreferences();
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionCreateInstance<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionCreateInstance,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionCreateInstance<<"()->"<<StatStr(st)<<std::endl;
# endif
if (st == kOfxStatOK) {
_created = true;
}
return st;
}
OfxStatus Instance::beginInstanceChangedAction(const std::string & why)
{
Property::PropSpec stuff[] = {
{ kOfxPropChangeReason, Property::eString, 1, true, why.c_str() },
Property::propSpecEnd
};
Property::Set inArgs(stuff);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceChanged<<"("<<why<<")"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionBeginInstanceChanged,this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceChanged<<"("<<why<<")->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::paramInstanceChangedAction(const std::string & paramName,
const std::string & why,
OfxTime time,
OfxPointD renderScale)
{
Param::Instance* param = getParam(paramName);
if(isClipPreferencesSlaveParam(paramName))
_clipPrefsDirty = true;
if (!param) {
return kOfxStatFailed;
}
Property::PropSpec stuff[] = {
{ kOfxPropType, Property::eString, 1, true, kOfxTypeParameter },
{ kOfxPropName, Property::eString, 1, true, paramName.c_str() },
{ kOfxPropChangeReason, Property::eString, 1, true, why.c_str() },
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(stuff);
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeParameter<<","<<paramName<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionInstanceChanged,this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionInstanceChanged<<"("<<kOfxTypeParameter<<","<<paramName<<","<<why<<","<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::clipInstanceChangedAction(const std::string & clipName,
const std::string & why,
OfxTime time,
OfxPointD renderScale)
{
_clipPrefsDirty = true;
std::map<std::string,ClipInstance*>::iterator it=_clips.find(clipName);
if(it!=_clips.end())
return (it->second)->instanceChangedAction(why,time,renderScale);
else
return kOfxStatFailed;
}
OfxStatus Instance::endInstanceChangedAction(const std::string & why)
{
Property::PropSpec whyStuff[] = {
{ kOfxPropChangeReason, Property::eString, 1, true, why.c_str() },
Property::propSpecEnd
};
Property::Set inArgs(whyStuff);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceChanged<<"("<<why<<")"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionEndInstanceChanged,this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceChanged<<"("<<why<<")->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::purgeCachesAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionPurgeCaches<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionPurgeCaches ,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionPurgeCaches<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::syncPrivateDataAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionSyncPrivateData<<"()"<<std::endl;
# endif
Property::Int* s = _properties.fetchIntProperty(kOfxPropParamSetNeedsSyncing);
bool needsSyncing = s ? s->getValue() : true;
OfxStatus st = kOfxStatReplyDefault;
if (needsSyncing) {
st = mainEntry(kOfxActionSyncPrivateData,this->getHandle(),0,0);
if (s) {
s->setValue(0);
}
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionSyncPrivateData<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::beginInstanceEditAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceEdit<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionBeginInstanceEdit,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionBeginInstanceEdit<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::endInstanceEditAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceEdit<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionEndInstanceEdit,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionEndInstanceEdit<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
# ifdef OFX_SUPPORTS_OPENGLRENDER
OfxStatus Instance::contextAttachedAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextAttached<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionOpenGLContextAttached,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextAttached<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::contextDetachedAction(){
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextDetached<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxActionOpenGLContextDetached,this->getHandle(),0,0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxActionOpenGLContextDetached<<"()->"<<StatStr(st)<<std::endl;
# endif
return st;
}
# endif
OfxStatus Instance::beginRenderAction(OfxTime startFrame,
OfxTime endFrame,
OfxTime step,
bool interactive,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender
)
{
Property::PropSpec stuff[] = {
{ kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropFrameStep, Property::eDouble, 1, true, "0" },
{ kOfxPropIsInteractive, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(stuff);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,startFrame, 0);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,endFrame, 1);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameStep,step);
inArgs.setIntProperty(kOfxPropIsInteractive,interactive);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender);
inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionBeginSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxImageEffectActionBeginSequenceRender, this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionBeginSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::renderAction(OfxTime time,
const std::string & field,
const OfxRectI &renderRoI,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender,
bool draftRender
)
{
static const Property::PropSpec inStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" },
{ kOfxImageEffectPropRenderWindow, Property::eInt, 4, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field);
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setIntPropertyN(kOfxImageEffectPropRenderWindow, &renderRoI.x1, 4);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender);
inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender);
inArgs.setIntProperty(kOfxImageEffectPropRenderQualityDraft,draftRender);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionRender<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxImageEffectActionRender,this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionRender<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxStatus Instance::endRenderAction(OfxTime startFrame,
OfxTime endFrame,
OfxTime step,
bool interactive,
OfxPointD renderScale,
bool sequentialRender,
bool interactiveRender
)
{
static const Property::PropSpec inStuff[] = {
{ kOfxImageEffectPropFrameRange, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropFrameStep, Property::eDouble, 1, true, "0" },
{ kOfxPropIsInteractive, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropSequentialRenderStatus, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropInteractiveRenderStatus, Property::eInt, 1, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameStep,step);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,startFrame, 0);
inArgs.setDoubleProperty(kOfxImageEffectPropFrameRange,endFrame, 1);
inArgs.setIntProperty(kOfxPropIsInteractive,interactive);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
inArgs.setIntProperty(kOfxImageEffectPropSequentialRenderStatus,sequentialRender);
inArgs.setIntProperty(kOfxImageEffectPropInteractiveRenderStatus,interactiveRender);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionEndSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxImageEffectActionEndSequenceRender,this->getHandle(), &inArgs, 0);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionEndSequenceRender<<"(("<<startFrame<<","<<endFrame<<"),"<<step<<","<<interactive<<",("<<renderScale.x<<","<<renderScale.y<<"),"<<sequentialRender<<","<<interactiveRender
<<")->"<<StatStr(st)<<std::endl;
# endif
return st;
}
OfxRectD Instance::calcDefaultRegionOfDefinition(OfxTime time,
OfxPointD ) const
{
OfxRectD rod;
if(
_context == kOfxImageEffectContextGenerator) {
rod.x1 = rod.y1 = 0;
getProjectExtent(rod.x2, rod.y2);
}
else if(_context == kOfxImageEffectContextFilter ||
_context == kOfxImageEffectContextPaint) {
ClipInstance *clip = getClip(kOfxImageEffectSimpleSourceClipName);
if(clip) {
rod = clip->getRegionOfDefinition(time);
} else {
throw Property::Exception(kOfxStatFailed);
}
}
else if(_context == kOfxImageEffectContextTransition) {
ClipInstance *clipFrom = getClip(kOfxImageEffectTransitionSourceFromClipName);
ClipInstance *clipTo = getClip(kOfxImageEffectTransitionSourceToClipName);
if(clipFrom && clipTo) {
rod = clipFrom->getRegionOfDefinition(time);
rod = Union(rod, clipTo->getRegionOfDefinition(time));
} else {
throw Property::Exception(kOfxStatFailed);
}
}
else if(_context == kOfxImageEffectContextGeneral
) {
bool gotOne = false;
for(std::map<std::string, ClipInstance*>::const_iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
if(!clip->isOutput() && (!clip->isOptional() || (clip->getConnected() && clip->getName() == kOfxImageEffectSimpleSourceClipName))) {
if(!gotOne)
rod = clip->getRegionOfDefinition(time);
else
rod = Union(rod, clip->getRegionOfDefinition(time));
gotOne = true;
}
}
if(!gotOne) {
rod.x1 = rod.y1 = 0;
getProjectExtent(rod.x2, rod.y2);
}
}
else if(_context == kOfxImageEffectContextRetimer) {
ClipInstance *clip = getClip(kOfxImageEffectSimpleSourceClipName);
if(clip) {
Param::DoubleInstance *param = dynamic_cast<Param::DoubleInstance *>(getParam(kOfxImageEffectRetimerParamName));
if(param) {
rod = clip->getRegionOfDefinition(floor(time));
rod = Union(rod, clip->getRegionOfDefinition(floor(time) + 1));
} else {
throw Property::Exception(kOfxStatFailed);
}
} else {
throw Property::Exception(kOfxStatFailed);
}
}
else {
throw Property::Exception(kOfxStatErrMissingHostFeature);
}
return rod;
}
OfxStatus Instance::getRegionOfDefinitionAction(OfxTime time,
OfxPointD renderScale,
OfxRectD &rod)
{
static const Property::PropSpec inStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
Property::propSpecEnd
};
static const Property::PropSpec outStuff[] = {
{ kOfxImageEffectPropRegionOfDefinition , Property::eDouble, 4, false, "0" },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
Property::Set outArgs(outStuff);
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetRegionOfDefinition<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl;
# endif
OfxStatus stat = mainEntry(kOfxImageEffectActionGetRegionOfDefinition,
this->getHandle(),
&inArgs,
&outArgs);
if(stat == kOfxStatOK) {
outArgs.getDoublePropertyN(kOfxImageEffectPropRegionOfDefinition, &rod.x1, 4);
}
else if(stat == kOfxStatReplyDefault) {
rod = calcDefaultRegionOfDefinition(time, renderScale);
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetRegionOfDefinition<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(stat);
if(stat == kOfxStatOK) {
std::cout << ": ("<<rod.x1<<","<<rod.y1<<","<<rod.x2<<","<<rod.y2<<")";
}
std::cout << std::endl;
# endif
return stat;
}
OfxStatus Instance::getRegionOfInterestAction(OfxTime time,
OfxPointD renderScale,
const OfxRectD &roi,
std::map<ClipInstance *, OfxRectD>& rois)
{
OfxStatus stat = kOfxStatReplyDefault;
rois.clear();
if(!supportsTiles()) {
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
if(!it->second->isOutput() ||
getContext() == kOfxImageEffectContextGenerator) {
if (it->second->isOutput() || it->second->getConnected()) { OfxRectD roi = it->second->getRegionOfDefinition(time);
rois[it->second] = roi;
}
}
}
stat = kOfxStatOK;
}
else {
static const Property::PropSpec inStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
{ kOfxImageEffectPropRegionOfInterest , Property::eDouble, 4, true, 0 },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setDoublePropertyN(kOfxImageEffectPropRegionOfInterest, &roi.x1, 4);
Property::Set outArgs;
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
if(!it->second->isOutput() ||
getContext() == kOfxImageEffectContextGenerator) {
Property::PropSpec s;
std::string name = "OfxImageClipPropRoI_"+it->first;
s.name = name.c_str();
s.type = Property::eDouble;
s.dimension = 4;
s.readonly = false;
s.defaultValue = "";
outArgs.createProperty(s);
outArgs.setDoublePropertyN(s.name, &roi.x1, 4);
}
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetRegionsOfInterest<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"),("<<roi.x1<<","<<roi.y1<<","<<roi.x2<<","<<roi.y2<<"))"<<std::endl;
# endif
stat = mainEntry(kOfxImageEffectActionGetRegionsOfInterest,
this->getHandle(),
&inArgs,
&outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetRegionsOfInterest<<"("<<time<<",("<<renderScale.x<<","<<renderScale.y<<"),("<<roi.x1<<","<<roi.y1<<","<<roi.x2<<","<<roi.y2<<"))->"<<StatStr(stat);
if (stat == kOfxStatOK) {
std::cout << ": ";
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
std::string name = "OfxImageClipPropRoI_"+it->first;
OfxRectD thisRoi;
thisRoi.x1 = outArgs.getDoubleProperty(name,0);
thisRoi.y1 = outArgs.getDoubleProperty(name,1);
thisRoi.x2 = outArgs.getDoubleProperty(name,2);
thisRoi.y2 = outArgs.getDoubleProperty(name,3);
std::cout << it->first << "->("<<thisRoi.x1<<","<<thisRoi.y1<<","<<thisRoi.x2<<","<<thisRoi.y2<<") ";
}
}
std::cout << std::endl;
# endif
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
if(!it->second->isOutput() ||
getContext() == kOfxImageEffectContextGenerator) {
if (it->second->isOutput() || it->second->getConnected()) {
if(it->second->supportsTiles()) {
std::string name = "OfxImageClipPropRoI_"+it->first;
OfxRectD thisRoi;
thisRoi.x1 = outArgs.getDoubleProperty(name,0);
thisRoi.y1 = outArgs.getDoubleProperty(name,1);
thisRoi.x2 = outArgs.getDoubleProperty(name,2);
thisRoi.y2 = outArgs.getDoubleProperty(name,3);
rois[it->second] = thisRoi;
}
else {
OfxRectD rod = it->second->getRegionOfDefinition(time
);
rois[it->second] = rod;
}
}
}
}
}
return stat;
}
OfxStatus Instance::getFrameNeededAction(OfxTime time,
RangeMap &rangeMap)
{
OfxStatus stat = kOfxStatReplyDefault;
Property::Set outArgs;
if(temporalAccess()) {
static const Property::PropSpec inStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
inArgs.setDoubleProperty(kOfxPropTime,time);
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
if(!it->second->isOutput()) {
Property::PropSpec s;
std::string name = "OfxImageClipPropFrameRange_"+it->first;
s.name = name.c_str();
s.type = Property::eDouble;
s.dimension = 0;
s.readonly = false;
s.defaultValue = "";
outArgs.createProperty(s);
outArgs.setDoubleProperty(name, time, 0);
outArgs.setDoubleProperty(name, time, 1);
}
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetFramesNeeded<<"("<<time<<")"<<std::endl;
# endif
stat = mainEntry(kOfxImageEffectActionGetFramesNeeded,
this->getHandle(),
&inArgs,
&outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetFramesNeeded<<"("<<time<<")->"<<StatStr(stat);
if (stat == kOfxStatOK) {
std::cout << ": ";
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
if(!clip->isOutput()) {
std::string name = "OfxImageClipPropFrameRange_"+it->first;
std::cout << it->first << "->[";
int nRanges = outArgs.getDimension(name);
for(int r=0;r<nRanges;){
double min = outArgs.getDoubleProperty(name,r);
double max = outArgs.getDoubleProperty(name,r+1);
r += 2;
std::cout <<"("<<min<<","<<max<<")";
if (r < nRanges-1) {
std::cout << ",";
}
}
std::cout << "]";
}
}
}
std::cout << std::endl;
# endif
}
OfxRangeD defaultRange;
defaultRange.min =
defaultRange.max = time;
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
if(!clip->isOutput()) {
if(stat != kOfxStatOK) {
rangeMap[clip].push_back(defaultRange);
}
else {
std::string name = "OfxImageClipPropFrameRange_"+it->first;
int nRanges = outArgs.getDimension(name);
if(nRanges%2 != 0)
return kOfxStatFailed;
if(nRanges == 0) {
rangeMap[clip].push_back(defaultRange);
}
else {
for(int r=0;r<nRanges;){
double min = outArgs.getDoubleProperty(name,r);
double max = outArgs.getDoubleProperty(name,r+1);
r += 2;
OfxRangeD range;
range.min = min;
range.max = max;
rangeMap[clip].push_back(range);
}
}
}
}
}
return stat;
}
OfxStatus Instance::isIdentityAction(OfxTime &time,
const std::string & field,
const OfxRectI &renderRoI,
OfxPointD renderScale,
std::string &clip)
{
static const Property::PropSpec inStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, true, "0" },
{ kOfxImageEffectPropFieldToRender, Property::eString, 1, true, "" },
{ kOfxImageEffectPropRenderWindow, Property::eInt, 4, true, "0" },
{ kOfxImageEffectPropRenderScale, Property::eDouble, 2, true, "0" },
Property::propSpecEnd
};
static const Property::PropSpec outStuff[] = {
{ kOfxPropTime, Property::eDouble, 1, false, "0.0" },
{ kOfxPropName, Property::eString, 1, false, "" },
Property::propSpecEnd
};
Property::Set inArgs(inStuff);
inArgs.setStringProperty(kOfxImageEffectPropFieldToRender,field);
inArgs.setDoubleProperty(kOfxPropTime,time);
inArgs.setIntPropertyN(kOfxImageEffectPropRenderWindow, &renderRoI.x1, 4);
inArgs.setDoublePropertyN(kOfxImageEffectPropRenderScale, &renderScale.x, 2);
Property::Set outArgs(outStuff);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionIsIdentity<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"))"<<std::endl;
# endif
outArgs.setDoubleProperty(kOfxPropTime,time);
OfxStatus st = mainEntry(kOfxImageEffectActionIsIdentity,
this->getHandle(),
&inArgs,
&outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionIsIdentity<<"("<<time<<","<<field<<",("<<renderRoI.x1<<","<<renderRoI.y1<<","<<renderRoI.x2<<","<<renderRoI.y2<<"),("<<renderScale.x<<","<<renderScale.y<<"))->"<<StatStr(st);
if(st==kOfxStatOK){
std::cout << ": "<<outArgs.getDoubleProperty(kOfxPropTime)<<","<<outArgs.getStringProperty(kOfxPropName);
}
std::cout<<std::endl;
# endif
if(st==kOfxStatOK){
time = outArgs.getDoubleProperty(kOfxPropTime);
clip = outArgs.getStringProperty(kOfxPropName);
}
return st;
}
bool Instance::isChromaticComponent(const std::string &str) const
{
if(str == kOfxImageComponentRGBA)
return true;
if(str == kOfxImageComponentRGB)
return true;
if(str == kOfxImageComponentAlpha)
return true;
return false;
}
bool Instance::canCurrentlyHandleMultipleClipDepths() const
{
bool hostSupports = gImageEffectHost->getProperties().getIntProperty(kOfxImageEffectPropSupportsMultipleClipDepths) != 0;;
bool pluginSupports = supportsMultipleClipDepths();
if(!hostSupports || !pluginSupports)
return false;
if(_context == kOfxImageEffectContextFilter)
return false;
if(_context == kOfxImageEffectContextGenerator ||
_context == kOfxImageEffectContextTransition ||
_context == kOfxImageEffectContextPaint ||
_context == kOfxImageEffectContextRetimer)
return false;
return true;
}
void Instance::setDefaultClipPreferences()
{
bool multiBitDepth = canCurrentlyHandleMultipleClipDepths();
bool hasSetCompsAndDepth = false;
std::string deepestBitDepth = kOfxBitDepthNone;
std::string mostComponents = kOfxImageComponentNone;
double frameRate = getFrameRate(); std::string premult = kOfxImageOpaque;
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
if(!clip->isOutput()) {
bool connected = clip->getConnected();
if (connected) {
frameRate = Maximum(frameRate, clip->getFrameRate());
}
std::string rawComp = clip->getUnmappedComponents();
rawComp = clip->findSupportedComp(rawComp);
const std::string &rawDepth = clip->getUnmappedBitDepth();
const std::string &rawPreMult = clip->getPremult();
if(isChromaticComponent(rawComp)) {
if(connected) {
if(rawPreMult == kOfxImagePreMultiplied)
premult = kOfxImagePreMultiplied;
else if(rawPreMult == kOfxImageUnPreMultiplied && premult != kOfxImagePreMultiplied)
premult = kOfxImageUnPreMultiplied;
}
if(connected) {
hasSetCompsAndDepth = true;
deepestBitDepth = FindDeepestBitDepth(deepestBitDepth, rawDepth);
mostComponents = findMostChromaticComponents(mostComponents, rawComp);
}
}
}
}
if (!hasSetCompsAndDepth) {
mostComponents = kOfxImageComponentRGBA;
deepestBitDepth = kOfxBitDepthFloat;
}
_outputFrameRate = frameRate;
_outputFielding = getDefaultOutputFielding();
_outputPreMultiplication = premult;
_continuousSamples = false;
_frameVarying = false;
deepestBitDepth = bestSupportedDepth(deepestBitDepth);
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
std::string comp, depth;
std::string rawComp = clip->getUnmappedComponents();
rawComp = clip->findSupportedComp(rawComp); const std::string &rawDepth = clip->getUnmappedBitDepth();
if(isChromaticComponent(rawComp)) {
if(clip->isOutput() || clip->isOptional()) {
depth = deepestBitDepth;
comp = clip->findSupportedComp(mostComponents);
clip->setPixelDepth(depth);
clip->setComponents(comp);
}
else {
comp = rawComp;
depth = multiBitDepth ? bestSupportedDepth(rawDepth) : deepestBitDepth;
clip->setPixelDepth(depth);
clip->setComponents(comp);
}
}
else {
clip->setPixelDepth(rawDepth);
clip->setComponents(rawComp);
}
}
}
void Instance::setupClipPreferencesArgs(Property::Set &outArgs)
{
setDefaultClipPreferences();
static const Property::PropSpec clipPrefsStuffs []=
{
{ kOfxImageEffectPropFrameRate, Property::eDouble, 1, false, "1" },
{ kOfxImageEffectPropPreMultiplication, Property::eString, 1, false, "" },
{ kOfxImageClipPropFieldOrder, Property::eString, 1, false, "" },
{ kOfxImageClipPropContinuousSamples, Property::eInt, 1, false, "0" },
{ kOfxImageEffectFrameVarying, Property::eInt, 1, false, "0" },
Property::propSpecEnd
};
outArgs.addProperties(clipPrefsStuffs);
bool multiBitDepth = canCurrentlyHandleMultipleClipDepths();
outArgs.setStringProperty(kOfxImageClipPropFieldOrder, _outputFielding);
outArgs.setStringProperty(kOfxImageEffectPropPreMultiplication, _outputPreMultiplication);
double projectPAR = getProjectPixelAspectRatio();
bool multipleClipsPAR = supportsMultipleClipPARs();
double inputPar;
bool inputParSet = false;
for (std::map<std::string, ClipInstance*>::iterator it2 = _clips.begin(); it2 != _clips.end(); ++it2) {
if (!it2->second->isOutput() && it2->second->getConnected()) {
if (!inputParSet) {
inputPar = it2->second->getAspectRatio();
inputParSet = true;
} else if (!multipleClipsPAR && inputPar != it2->second->getAspectRatio()) {
throw Property::Exception(kOfxStatErrValue);
}
}
}
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
std::string componentParamName = "OfxImageClipPropComponents_"+it->first;
std::string depthParamName = "OfxImageClipPropDepth_"+it->first;
std::string parParamName = "OfxImageClipPropPAR_"+it->first;
Property::PropSpec specComp = {componentParamName.c_str(), Property::eString, 0, false, ""}; outArgs.createProperty(specComp);
outArgs.setStringProperty(componentParamName.c_str(), clip->getComponents().c_str());
Property::PropSpec specDep = {depthParamName.c_str(), Property::eString, 1, !multiBitDepth, clip->getPixelDepth().c_str()};
outArgs.createProperty(specDep);
Property::PropSpec specPAR = {parParamName.c_str(), Property::eDouble, 1, false, "1"};
outArgs.createProperty(specPAR);
if (!clip->isOutput()) {
double par;
if (!multipleClipsPAR && inputParSet) {
par = inputPar;
} else if (multipleClipsPAR) {
par = clip->getAspectRatio();
} else {
par = projectPAR;
}
outArgs.setDoubleProperty(parParamName, par);
} else {
outArgs.setDoubleProperty(parParamName, inputParSet ? inputPar : projectPAR);
}
}
bool outputFrameRateSet = false;
double outputFrameRate = _outputFrameRate;
for (std::map<std::string, ClipInstance*>::iterator it2 = _clips.begin(); it2 != _clips.end(); ++it2) {
if (!it2->second->isOutput() && it2->second->getConnected()) {
if (!outputFrameRateSet) {
outputFrameRate = it2->second->getFrameRate();
outputFrameRateSet = true;
} else if (outputFrameRate != it2->second->getFrameRate()) {
throw Property::Exception(kOfxStatErrValue);
}
}
}
outArgs.setDoubleProperty(kOfxImageEffectPropFrameRate, outputFrameRate);
}
bool Instance::getClipPreferences()
{
Property::Set outArgs;
setupClipPreferencesArgs(outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetClipPreferences<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxImageEffectActionGetClipPreferences,
this->getHandle(),
0,
&outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetClipPreferences<<"()->"<<StatStr(st);
# endif
if(st!=kOfxStatOK && st!=kOfxStatReplyDefault) {
# ifdef OFX_DEBUG_ACTIONS
std::cout << std::endl;
# endif
return false;
}
# ifdef OFX_DEBUG_ACTIONS
std::cout << ": ";
# endif
for(std::map<std::string, ClipInstance*>::iterator it=_clips.begin();
it!=_clips.end();
++it) {
ClipInstance *clip = it->second;
std::string componentParamName = "OfxImageClipPropComponents_"+it->first;
std::string depthParamName = "OfxImageClipPropDepth_"+it->first;
std::string parParamName = "OfxImageClipPropPAR_"+it->first;
# ifdef OFX_DEBUG_ACTIONS
std::cout << it->first<<"->"<<outArgs.getStringProperty(depthParamName)<<","<<outArgs.getStringProperty(componentParamName)<<","<<outArgs.getDoubleProperty(parParamName)<<" ";
# endif
clip->setPixelDepth(outArgs.getStringProperty(depthParamName));
clip->setComponents(outArgs.getStringProperty(componentParamName));
}
_outputFrameRate = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRate);
_outputFielding = outArgs.getStringProperty(kOfxImageClipPropFieldOrder);
_outputPreMultiplication = outArgs.getStringProperty(kOfxImageEffectPropPreMultiplication);
_continuousSamples = outArgs.getIntProperty(kOfxImageClipPropContinuousSamples) != 0;
_frameVarying = outArgs.getIntProperty(kOfxImageEffectFrameVarying) != 0;
# ifdef OFX_DEBUG_ACTIONS
std::cout << _outputFrameRate<<","<<_outputFielding<<","<<_outputPreMultiplication<<","<<_continuousSamples<<","<<_frameVarying<<std::endl;
# endif
_clipPrefsDirty = false;
return true;
}
const std::string &Instance::findMostChromaticComponents(const std::string &a, const std::string &b) const
{
if(a == kOfxImageComponentNone)
return b;
if(a == kOfxImageComponentRGBA)
return a;
if(b == kOfxImageComponentRGBA)
return b;
if(a == kOfxImageComponentRGB)
return a;
if(b == kOfxImageComponentRGB)
return b;
return a;
}
const std::string &Instance::bestSupportedDepth(const std::string &depth) const
{
static const std::string none(kOfxBitDepthNone);
static const std::string bytes(kOfxBitDepthByte);
static const std::string shorts(kOfxBitDepthShort);
static const std::string halfs(kOfxBitDepthHalf);
static const std::string floats(kOfxBitDepthFloat);
if(depth == none)
return none;
if(isPixelDepthSupported(depth))
return depth;
if(depth == floats) {
if(isPixelDepthSupported(shorts))
return shorts;
if(isPixelDepthSupported(bytes))
return bytes;
}
if(depth == halfs) {
if(isPixelDepthSupported(floats))
return floats;
if(isPixelDepthSupported(shorts))
return shorts;
if(isPixelDepthSupported(bytes))
return bytes;
}
if(depth == shorts) {
if(isPixelDepthSupported(floats))
return floats;
if(isPixelDepthSupported(bytes))
return bytes;
}
if(depth == bytes) {
if(isPixelDepthSupported(shorts))
return shorts;
if(isPixelDepthSupported(floats))
return floats;
}
return none;
}
Interact::Descriptor &Instance::getOverlayDescriptor(int bitDepthPerComponent, bool hasAlpha)
{
return _descriptor->getOverlayDescriptor(bitDepthPerComponent, hasAlpha);
}
OfxStatus Instance::getTimeDomainAction(OfxRangeD& range)
{
static const Property::PropSpec outStuff[] = {
{ kOfxImageEffectPropFrameRange , Property::eDouble, 2, false, "0.0" },
Property::propSpecEnd
};
Property::Set outArgs(outStuff);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetTimeDomain<<"()"<<std::endl;
# endif
OfxStatus st = mainEntry(kOfxImageEffectActionGetTimeDomain,
this->getHandle(),
0,
&outArgs);
# ifdef OFX_DEBUG_ACTIONS
std::cout << "OFX: "<<(void*)this<<"->"<<kOfxImageEffectActionGetTimeDomain<<"()->"<<StatStr(st);
if (st == kOfxStatOK) {
std::cout << ": ("<<outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,0)<<","<<outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,1)<<")";
}
std::cout << std::endl;
# endif
if(st!=kOfxStatOK) return st;
range.min = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,0);
range.max = outArgs.getDoubleProperty(kOfxImageEffectPropFrameRange,1);
return kOfxStatOK;
}
void Instance::paramChangedByPlugin(Param::Instance *param)
{
if (!_created) {
return;
}
double frame = getFrameRecursive();
OfxPointD renderScale; getRenderScaleRecursive(renderScale.x, renderScale.y);
beginInstanceChangedAction(kOfxChangePluginEdited);
paramInstanceChangedAction(param->getName(), kOfxChangePluginEdited, frame, renderScale);
endInstanceChangedAction(kOfxChangePluginEdited);
}
static OfxStatus getPropertySet(OfxImageEffectHandle h1,
OfxPropertySetHandle *h2)
{
try {
if (!h2) {
return kOfxStatErrBadHandle;
}
Base *effectBase = reinterpret_cast<Base*>(h1);
if (!effectBase || !effectBase->verifyMagic()) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
*h2 = effectBase->getProps().getHandle();
return kOfxStatOK;
} catch (...) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus getParamSet(OfxImageEffectHandle h1,
OfxParamSetHandle *h2)
{
try {
if (!h2) {
return kOfxStatErrBadHandle;
}
ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(h1);
if (!effectBase || !effectBase->verifyMagic()) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
ImageEffect::Descriptor *effectDescriptor = dynamic_cast<ImageEffect::Descriptor*>(effectBase);
if(effectDescriptor) {
*h2 = effectDescriptor->getParamSetHandle();
return kOfxStatOK;
}
ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase);
if(effectInstance) {
*h2 = effectInstance->getParamSetHandle();
return kOfxStatOK;
}
*h2 = NULL;
return kOfxStatErrBadHandle;
} catch (...) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipDefine(OfxImageEffectHandle h1,
const char *name,
OfxPropertySetHandle *h2)
{
try {
if (!h2) {
return kOfxStatErrBadHandle;
}
ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(h1);
if (!effectBase || !effectBase->verifyMagic()) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
ImageEffect::Descriptor *effectDescriptor = dynamic_cast<ImageEffect::Descriptor*>(effectBase);
if(effectDescriptor){
ClipDescriptor *clip = effectDescriptor->defineClip(name);
*h2 = clip->getPropHandle();
return kOfxStatOK;
}
*h2 = NULL;
return kOfxStatErrBadHandle;
} catch (...) {
*h2 = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipGetPropertySet(OfxImageClipHandle clip,
OfxPropertySetHandle *propHandle){
try {
if (!propHandle) {
return kOfxStatErrBadHandle;
}
ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip);
if (!clipInstance || !clipInstance->verifyMagic()) {
*propHandle = NULL;
return kOfxStatErrBadHandle;
}
*propHandle = clipInstance->getPropHandle();
return kOfxStatOK;
} catch (...) {
*propHandle = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipGetImage(OfxImageClipHandle h1,
OfxTime time,
const OfxRectD *h2,
OfxPropertySetHandle *h3)
{
try {
if (!h3) {
return kOfxStatErrBadHandle;
}
ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(h1);
if (!clipInstance || !clipInstance->verifyMagic()) {
*h3 = NULL;
return kOfxStatErrBadHandle;
}
Image* image = clipInstance->getImage(time,h2);
if(!image) {
*h3 = NULL;
return kOfxStatFailed;
}
*h3 = image->getPropHandle();
return kOfxStatOK;
} catch (...) {
*h3 = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipReleaseImage(OfxPropertySetHandle h1)
{
try {
Property::Set *pset = reinterpret_cast<Property::Set*>(h1);
if (!pset || !pset->verifyMagic()) {
return kOfxStatErrBadHandle;
}
Image *image = dynamic_cast<Image*>(pset);
if(image){
image->releaseReference();
return kOfxStatOK;
}
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipGetHandle(OfxImageEffectHandle imageEffect,
const char *name,
OfxImageClipHandle *clip,
OfxPropertySetHandle *propertySet)
{
try {
if (!clip) {
return kOfxStatErrBadHandle;
}
ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(imageEffect);
if (!effectBase || !effectBase->verifyMagic()) {
return kOfxStatErrBadHandle;
}
ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(effectBase);
if(effectInstance){
ClipInstance* instance = effectInstance->getClip(name);
if(!instance)
return kOfxStatErrBadHandle;
*clip = instance->getHandle();
if(propertySet)
*propertySet = instance->getPropHandle();
return kOfxStatOK;
}
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipGetRegionOfDefinition(OfxImageClipHandle clip,
OfxTime time,
OfxRectD *bounds)
{
try {
if (!bounds) {
return kOfxStatErrBadHandle;
}
ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(clip);
if (!clipInstance || !clipInstance->verifyMagic()) {
bounds->x1 = bounds->y1 = bounds->x2 = bounds->y2 = 0.;
return kOfxStatErrBadHandle;
}
*bounds = clipInstance->getRegionOfDefinition(time);
if (bounds->x2 < bounds->x1 || bounds->y2 < bounds->y1) {
return kOfxStatFailed;
}
return kOfxStatOK;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static int abort(OfxImageEffectHandle imageEffect)
{
try {
ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(imageEffect);
if (!effectBase || !effectBase->verifyMagic()) {
return kOfxStatErrBadHandle;
}
ImageEffect::Instance *effectInstance = dynamic_cast<ImageEffect::Instance*>(effectBase);
if(effectInstance)
return effectInstance->abort();
else
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static OfxStatus imageMemoryAlloc(OfxImageEffectHandle instanceHandle,
size_t nBytes,
OfxImageMemoryHandle *memoryHandle)
{
try {
if (!memoryHandle) {
return kOfxStatErrBadHandle;
}
ImageEffect::Base *effectBase = reinterpret_cast<ImageEffect::Base*>(instanceHandle);
ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(effectBase);
Memory::Instance* memory;
if(effectInstance){
if (!effectInstance->verifyMagic()) {
*memoryHandle = NULL;
return kOfxStatErrBadHandle;
}
memory = effectInstance->imageMemoryAlloc(nBytes);
}
else {
memory = gImageEffectHost->imageMemoryAlloc(nBytes);
}
if (memory) {
*memoryHandle = memory->getHandle();
return kOfxStatOK;
} else {
*memoryHandle = NULL;
return kOfxStatErrMemory;
}
} catch (std::bad_alloc) {
*memoryHandle = NULL;
return kOfxStatErrMemory;
} catch (...) {
*memoryHandle = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus imageMemoryFree(OfxImageMemoryHandle memoryHandle){
try {
Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle);
if(memoryInstance && memoryInstance->verifyMagic()) {
memoryInstance->freeMem();
delete memoryInstance;
return kOfxStatOK;
}
else
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static
OfxStatus imageMemoryLock(OfxImageMemoryHandle memoryHandle,
void **returnedPtr){
try {
if (!returnedPtr) {
return kOfxStatErrBadHandle;
}
Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle);
if(memoryInstance && memoryInstance->verifyMagic()) {
memoryInstance->lock();
*returnedPtr = memoryInstance->getPtr();
return (*returnedPtr) ? kOfxStatOK : kOfxStatErrMemory;
}
*returnedPtr = NULL;
return kOfxStatErrBadHandle;
} catch (...) {
*returnedPtr = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus imageMemoryUnlock(OfxImageMemoryHandle memoryHandle){
try {
Memory::Instance *memoryInstance = reinterpret_cast<Memory::Instance*>(memoryHandle);
if(memoryInstance && memoryInstance->verifyMagic()){
memoryInstance->unlock();
return kOfxStatOK;
}
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static const struct OfxImageEffectSuiteV1 gImageEffectSuite = {
getPropertySet,
getParamSet,
clipDefine,
clipGetHandle,
clipGetPropertySet,
clipGetImage,
clipReleaseImage,
clipGetRegionOfDefinition,
abort,
imageMemoryAlloc,
imageMemoryFree,
imageMemoryLock,
imageMemoryUnlock
};
# ifdef OFX_SUPPORTS_OPENGLRENDER
static OfxStatus clipLoadTexture(OfxImageClipHandle h1,
OfxTime time,
const char *format,
const OfxRectD *h2,
OfxPropertySetHandle *h3)
{
try {
if (!h3) {
return kOfxStatErrBadHandle;
}
ClipInstance *clipInstance = reinterpret_cast<ClipInstance*>(h1);
if (!clipInstance || !clipInstance->verifyMagic()) {
return kOfxStatErrBadHandle;
}
if(clipInstance){
Texture* texture = clipInstance->loadTexture(time,format,h2);
if(!texture) {
*h3 = NULL;
return kOfxStatFailed;
}
*h3 = texture->getPropHandle();
return kOfxStatOK;
}
return kOfxStatErrBadHandle;
} catch (...) {
*h3 = NULL;
return kOfxStatErrBadHandle;
}
}
static OfxStatus clipFreeTexture(OfxPropertySetHandle h1)
{
try {
Property::Set *pset = reinterpret_cast<Property::Set*>(h1);
if (!pset || !pset->verifyMagic()) {
return kOfxStatErrBadHandle;
}
Texture *texture = dynamic_cast<Texture*>(pset);
if(texture){
texture->releaseReference();
return kOfxStatOK;
}
else
return kOfxStatErrBadHandle;
} catch (...) {
return kOfxStatErrBadHandle;
}
}
static OfxStatus flushResources( )
{
return gImageEffectHost->flushOpenGLResources();
}
static const struct OfxImageEffectOpenGLRenderSuiteV1 gOpenGLRenderSuite = {
clipLoadTexture,
clipFreeTexture,
flushResources
};
# endif
static OfxStatus message(void *handle, const char *type, const char *id, const char *format, ...)
{
try {
ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle);
OfxStatus stat;
if(effectInstance){
va_list args;
va_start(args,format);
stat = effectInstance->vmessage(type,id,format,args);
va_end(args);
}
else{
va_list args;
va_start(args,format);
vprintf(format,args);
va_end(args);
stat = kOfxStatErrBadHandle;
}
return stat;
} catch (...) {
return kOfxStatFailed;
}
}
static OfxStatus setPersistentMessage(void *handle, const char *type, const char *id, const char *format, ...)
{
try {
ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle);
OfxStatus stat;
if(effectInstance){
va_list args;
va_start(args,format);
stat = effectInstance->setPersistentMessage(type,id,format,args);
va_end(args);
}
else{
va_list args;
va_start(args,format);
vprintf(format,args);
va_end(args);
stat = kOfxStatErrBadHandle;
}
return stat;
} catch (...) {
return kOfxStatFailed;
}
}
static OfxStatus clearPersistentMessage(void *handle)
{
try {
ImageEffect::Instance *effectInstance = reinterpret_cast<ImageEffect::Instance*>(handle);
OfxStatus stat;
if(effectInstance){
stat = effectInstance->clearPersistentMessage();
}
else{
stat = kOfxStatErrBadHandle;
}
return stat;
} catch (...) {
return kOfxStatFailed;
}
}
static const struct OfxMessageSuiteV2 gMessageSuite = {
message,
setPersistentMessage,
clearPersistentMessage
};
OverlayInteract::OverlayInteract(ImageEffect::Instance &effect, int bitDepthPerComponent, bool hasAlpha)
: Interact::Instance(effect.getOverlayDescriptor(bitDepthPerComponent, hasAlpha),
(void *)(effect.getHandle()))
, _instance(effect)
{
}
static OfxStatus ProgressStartV1(void *effectInstance,
const char *label)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
me->progressStart(label, "");
return kOfxStatOK;
}
static OfxStatus ProgressStart(void *effectInstance,
const char *message,
const char *messageid)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
me->progressStart(message, messageid);
return kOfxStatOK;
}
static OfxStatus ProgressEnd(void *effectInstance)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
me->progressEnd();
return kOfxStatOK;
}
static OfxStatus ProgressUpdate(void *effectInstance, double progress)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
bool v = me->progressUpdate(progress);
return v ? kOfxStatOK : kOfxStatReplyNo;
}
struct OfxProgressSuiteV1 gProgressSuiteV1 = {
ProgressStartV1,
ProgressUpdate,
ProgressEnd
};
struct OfxProgressSuiteV2 gProgressSuiteV2 = {
ProgressStart,
ProgressUpdate,
ProgressEnd
};
static OfxStatus TimeLineGetTime(void *effectInstance, double *time)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
*time = me->timeLineGetTime();
return kOfxStatOK;
}
static OfxStatus TimeLineGotoTime(void *effectInstance, double time)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
me->timeLineGotoTime(time);
return kOfxStatOK;
}
static OfxStatus TimeLineGetBounds(void *effectInstance, double *firstTime, double *lastTime)
{
if (!effectInstance)
return kOfxStatErrBadHandle;
Instance *me = reinterpret_cast<Instance *>(effectInstance);
me->timeLineGetBounds(*firstTime, *lastTime);
return kOfxStatOK;
}
struct OfxTimeLineSuiteV1 gTimelineSuite = {
TimeLineGetTime,
TimeLineGotoTime,
TimeLineGetBounds
};
#ifdef OFX_SUPPORTS_MULTITHREAD
static OfxStatus multiThread(OfxThreadFunctionV1 func,
unsigned int nThreads,
void *customArg)
{
return gImageEffectHost->multiThread(func, nThreads, customArg);
}
static OfxStatus multiThreadNumCPUs(unsigned int *nCPUs)
{
return gImageEffectHost->multiThreadNumCPUS(nCPUs);
}
static OfxStatus multiThreadIndex(unsigned int *threadIndex){
return gImageEffectHost->multiThreadIndex(threadIndex);
}
static int multiThreadIsSpawnedThread(void){
return gImageEffectHost->multiThreadIsSpawnedThread();
}
static OfxStatus mutexCreate(OfxMutexHandle *mutex, int lockCount)
{
return gImageEffectHost->mutexCreate(mutex, lockCount);
}
static OfxStatus mutexDestroy(const OfxMutexHandle mutex)
{
return gImageEffectHost->mutexDestroy(mutex);
}
static OfxStatus mutexLock(const OfxMutexHandle mutex){
return gImageEffectHost->mutexLock(mutex);
}
static OfxStatus mutexUnLock(const OfxMutexHandle mutex){
return gImageEffectHost->mutexUnLock(mutex);
}
static OfxStatus mutexTryLock(const OfxMutexHandle mutex){
return gImageEffectHost->mutexTryLock(mutex);
}
#else
static OfxStatus multiThread(OfxThreadFunctionV1 func,
unsigned int ,
void *customArg)
{
if (!func)
return kOfxStatFailed;
func(0,1,customArg);
return kOfxStatOK;
}
static OfxStatus multiThreadNumCPUs(unsigned int *nCPUs)
{
if (!nCPUs)
return kOfxStatFailed;
*nCPUs = 1;
return kOfxStatOK;
}
static OfxStatus multiThreadIndex(unsigned int *threadIndex){
if (!threadIndex)
return kOfxStatFailed;
*threadIndex = 0;
return kOfxStatOK;
}
static int multiThreadIsSpawnedThread(void){
return false;
}
static OfxStatus mutexCreate(OfxMutexHandle *mutex, int )
{
if (!mutex)
return kOfxStatFailed;
*mutex = 0;
return kOfxStatOK;
}
static OfxStatus mutexDestroy(const OfxMutexHandle mutex)
{
if (mutex != 0)
return kOfxStatErrBadHandle;
return kOfxStatOK;
}
static OfxStatus mutexLock(const OfxMutexHandle mutex){
if (mutex != 0)
return kOfxStatErrBadHandle;
return kOfxStatOK;
}
static OfxStatus mutexUnLock(const OfxMutexHandle mutex){
if (mutex != 0)
return kOfxStatErrBadHandle;
return kOfxStatOK;
}
static OfxStatus mutexTryLock(const OfxMutexHandle mutex){
if (mutex != 0)
return kOfxStatErrBadHandle;
return kOfxStatOK;
}
#endif
static const struct OfxMultiThreadSuiteV1 gMultiThreadSuite = {
multiThread,
multiThreadNumCPUs,
multiThreadIndex,
multiThreadIsSpawnedThread,
mutexCreate,
mutexDestroy,
mutexLock,
mutexUnLock,
mutexTryLock
};
static const Property::PropSpec hostStuffs[] = {
{ kOfxImageEffectHostPropIsBackground, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropSupportsOverlays, Property::eInt, 1, true, "1" },
{ kOfxImageEffectPropSupportsMultiResolution, Property::eInt, 1, true, "1" },
{ kOfxImageEffectPropSupportsTiles, Property::eInt, 1, true, "1" },
{ kOfxImageEffectPropTemporalClipAccess, Property::eInt, 1, true, "1" },
{ kOfxImageEffectPropSupportedComponents, Property::eString, 0, true, "" },
{ kOfxImageEffectPropSupportedPixelDepths, Property::eString, 0, true, "" },
{ kOfxImageEffectPropSupportedContexts, Property::eString, 0, true, "" },
{ kOfxImageEffectPropSupportsMultipleClipDepths, Property::eInt, 1, true, "1" },
{ kOfxImageEffectPropSupportsMultipleClipPARs, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropSetableFrameRate, Property::eInt, 1, true, "0" },
{ kOfxImageEffectPropSetableFielding, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropSupportsCustomInteract, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropSupportsStringAnimation, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropSupportsChoiceAnimation, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropSupportsBooleanAnimation, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropSupportsCustomAnimation, Property::eInt, 1, true, "0" },
{ kOfxPropHostOSHandle, Property::ePointer, 1, true, NULL },
#ifdef OFX_SUPPORTS_PARAMETRIC
{ kOfxParamHostPropSupportsParametricAnimation, Property::eInt, 1, true, "0"},
#endif
{ kOfxParamHostPropMaxParameters, Property::eInt, 1, true, "-1" },
{ kOfxParamHostPropMaxPages, Property::eInt, 1, true, "0" },
{ kOfxParamHostPropPageRowColumnCount, Property::eInt, 2, true, "0" },
{ kOfxImageEffectInstancePropSequentialRender, Property::eInt, 1, true, "0" }, #ifdef OFX_SUPPORTS_OPENGLRENDER
{ kOfxImageEffectPropOpenGLRenderSupported, Property::eString, 1, true, "false"}, #endif
{ kOfxImageEffectPropRenderQualityDraft, Property::eInt, 1, true, "0" }, { kOfxImageEffectHostPropNativeOrigin, Property::eString, 0, true, kOfxHostNativeOriginBottomLeft }, { kOfxImageEffectPropCudaRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropCudaStreamSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropMetalRenderSupported, Property::eString, 1, false, "false" },
{ kOfxImageEffectPropOpenCLRenderSupported, Property::eString, 1, false, "false" },
Property::propSpecEnd
};
Host::Host()
{
_properties.addProperties(hostStuffs);
}
void Host::initDescriptor(Descriptor* )
{
}
void Host::loadingStatus(const std::string &)
{
}
bool Host::pluginSupported(ImageEffectPlugin *, std::string &) const
{
return true;
}
Memory::Instance* Host::newMemoryInstance(size_t ) {
return 0;
}
Memory::Instance* Host::imageMemoryAlloc(size_t nBytes){
Memory::Instance* instance = newMemoryInstance(nBytes);
if(instance)
return instance;
else{
Memory::Instance* instance = new Memory::Instance;
instance->alloc(nBytes);
return instance;
}
}
const void *Host::fetchSuite(const char *suiteName, int suiteVersion)
{
if (strcmp(suiteName, kOfxImageEffectSuite)==0) {
if(suiteVersion==1)
return (void *)&gImageEffectSuite;
else
return NULL;
}
else if (strcmp(suiteName, kOfxParameterSuite)==0) {
return Param::GetSuite(suiteVersion);
}
else if (strcmp(suiteName, kOfxMessageSuite)==0) {
if(suiteVersion==1 || suiteVersion==2)
return (void *)&gMessageSuite;
else
return NULL;
}
else if (strcmp(suiteName, kOfxInteractSuite)==0) {
return Interact::GetSuite(suiteVersion);
}
else if (strcmp(suiteName, kOfxProgressSuite)==0) {
if(suiteVersion==1)
return (void*)&gProgressSuiteV1;
else if(suiteVersion==2)
return (void*)&gProgressSuiteV2;
else
return 0;
}
else if (strcmp(suiteName, kOfxTimeLineSuite)==0) {
if(suiteVersion==1)
return (void*)&gTimelineSuite;
else
return 0;
}
else if (strcmp(suiteName, kOfxMultiThreadSuite)==0) {
if(suiteVersion == 1)
return (void*)&gMultiThreadSuite;
else
return NULL;
}
# ifdef OFX_SUPPORTS_OPENGLRENDER
else if (strcmp(suiteName, kOfxOpenGLRenderSuite)==0) {
if(suiteVersion == 1)
return (void*)&gOpenGLRenderSuite;
else
return NULL;
}
# endif
# ifdef OFX_SUPPORTS_PARAMETRIC
else if (strcmp(suiteName, kOfxParametricParameterSuite)==0) {
return ParametricParam::GetSuite(suiteVersion);
}
# endif
else return OFX::Host::Host::fetchSuite(suiteName, suiteVersion);
}
}
}
}